+ -
当前位置:首页 → 问答吧 → 忽发其想

忽发其想

时间:2014-03-01

来源:互联网

C++11提供左lambda功能
也提供左std::function....用来把function物件化

但问题来了

lambda最大特徵就系外部变数引用...
如果....外部变数被毁灭左.....到底C++11的lambda会发生甚么事..??

当然...如果系pass by value就冇咩问题...
但pass by pointer/reference的话问题就大了....更何况大量使用pointer/reference才是C++的本色

以下code例子
VC++ 2012的debug和release mode会有不同结果
复制内容到剪贴板代码:function<int()> foo(function<int()> dummy)
{
int i = 0;
cout << "&i: " << &i << endl;
function<int()> result = [&]()
{
++i;
cout << "&i: " << &i << endl;
return i;
};
return result;
}
function<int()> foo2(function<int()> outer)
{
int i = 5;
cout << "&i: " << &i << endl;
cout << "i: " << outer() << endl;
return outer;
}

void main()
{
system("color 0a");

int a = 0;
cout << "&a: " << &a << endl;

function<int()> dummy;
auto functor = foo(dummy);
cout << "i: " << functor() << endl;

foo2(functor);

while(true);
}
debug mode的话...外部变数被毁灭...但第二次写入动作才弹出error
release mode的话...外部变数还生存...而且还"正确地"显示出记忆体位置和做两次operator ++....并显示出答案"1"和"2"
而foo2的i...原本谂住在相同的function开端结构的话...在stack上会建立出相同的资料结构...
所以想试试覆写掉stack上的记忆体...结果不成功

[ 本帖最后由 Susan﹏汪汪 於 2014-2-17 01:34 AM 编辑 ]

作者: Susan﹏汪汪   发布时间: 2014-03-01

如果要解释的话....debug mode的系正确运行程式
而release mode系部分正确的运行程式

首先...当foo做左return后...变数i即时被毁灭
所以所占用的记忆体应该已归还给系统
而debug mode就在第二次写入动作才侦测到error (OMG)

但release mode的话....
它没有毁灭变数i...还留在使用理应系VC++的大错处
但不要忘掉C++系有inline function
即系话foo本身已经做了inline处理...而变数i其实已经系main的变数
那么就表示...程式只是正确地读取/写入main的变数i而已

作者: Susan﹏汪汪   发布时间: 2014-03-01

另外....
最近因为外面有人做闹钟
汪汪就去研究过关於平行运算...和timer的问题...
发现原来window的timer api出奇地易用(当然以所有参数都使用预设值作大前提)

汪汪把丑陋的window timer api包装了一个class...然后再使用
不过还有个问题....
就是...因为window的timer并没有排队的观念...时间一到就马上create新thread
所以如果当timer create一个thread后....个thread运算过长时间...
在不停create新thread的情况下就变成大混乱

所以汪汪还不知道....系咪应该加一些控制...例如加锁防止data race
但是未在前thread结束...就已经不停create新thread的问题还是不能控制
复制内容到剪贴板代码:string placeValueNotation(uintmax_t x, uintmax_t n)
{
const char list[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string result;

if(x == 0) return "0";

while(x)
{
result = list[x % n] + result;
x /= n;
}

return result;
}

void main()
{
system("color 0a");
default_random_engine generator;
auto GetRandom = bind(uniform_int_distribution<uintmax_t>(0, 9999999999999999999), std::ref(generator));

uintmax_t count = 0, fps = 10;
timer timer([&]()
{
system("cls");

cout << placeValueNotation(GetRandom(), 16) << endl;
cout << count / fps << '.' << count % fps << endl;

++count;

}, 0, 1000 / fps);

while(true);
}

作者: Susan﹏汪汪   发布时间: 2014-03-01

我用 GCC 4.8.1,无用同有用优化(-O2),结果亦都不一样。前者显示 i 嘅值,依次为 0 同 6;而后者两次都系 1。
得到唔同结果,正正表示你咁嘅用法,行为不被定义。

以下系讲解 lambda 用法网页(网址:http://www.cprogramming.com/c++11/c++11-lambda-closures.html)其中一段:
引用:When you capture by reference, the lambda function is capable of modifying the local variable outside the lambda function--it is, after all, a reference. But this also means that if you return a lamba function from a function, you shouldn't use capture-by-reference because the reference will not be valid after the function returns.
C/C++ 有好多地方,规格讲明系行为不被定义。正如好多人都知,唔可以将函数内嘅区域变数嘅地址传回,然后取或赋值一样:
复制内容到剪贴板代码:int* foo() {
int i = 0;
return &i;
}

int bar() {
int j = 99;
return j;
}

int mai() {
int *pi = foo();
cout << *pi << endl;
bar();
++(*pi);
cout << *pi << endl;
}

作者: fitcat07   发布时间: 2014-03-01

引用:原帖由 Susan﹏汪汪 於 2014-2-17 03:50 AM 发表
另外....
最近因为外面有人做闹钟
汪汪就去研究过关於平行运算...和timer的问题...
发现原来window的timer api出奇地易用(当然以所有参数都使用预设值作大前提)

汪汪把丑陋的window timer api包装了一个class. ...
原来Window timer API有个flag....正正系汪汪想要的处理data race方法的效果

作者: Susan﹏汪汪   发布时间: 2014-03-01

热门下载

更多