2017-09-25 85 views
0

环境令人惊讶值:vs2013 RC5/vs2017;
项目:Win32控制台应用程序;约Lambda和cin.get

表示:编译和运行了一小会儿,然后中断和观看变量 “TASK_”;
如果 “add_task(&测试::打印,&吨,STR,10)”,在主FUNC中, “TASK_” 是正确值;

但是如果在func mytest中“add_task(& Test :: print,& t,str,10)”,则“task_”是错误的值;如果用while(1){}替换std :: cin.get(),它会右转;


#include <iostream> 
#include <string> 
#include <chrono> 
#include <thread> 
#include <functional> 

using task_t = std::function<void()>; 

class Test 
{ 
public: 
    void print(const std::string& str, int i) 
    { 
    std::cout << "Test: " << str << ", i: " << i << std::endl; 
    } 
}; 

template<typename Function, typename Self, typename... Args> 
void add_task(const Function& func, Self* self, Args... args) 
{ 
    task_t task = [&func, &self, args...]{ return (*self.*func)(args...); };  
    task_ = task; 
} 

Test t; 
std::string str = "Hello world"; 

task_t task_ = nullptr; 

void mytest() 
{ 
    add_task(&Test::print, &t, str, 10); 
} 

int main() 
{ 
    mytest(); 
    std::cin.get(); 
    return 0; 
} 
+0

错误值:空隙(无效){FUNC = 0xa4509c83自我= 0x0f93c1b0 {msvcp120d.dll的std :: basic_ostream <炭的std :: char_traits >的std :: COUT} {。 ..} ...} – fredirty2017

+0

正确的值:无效(无效){FUNC = {0x00b51087测试tp_test.exe ::打印(类的std :: basic_string的<字符,结构的std :: char_traits ,类std :: allocator > const&,int)} ...} – fredirty2017

回答

0

在C++中,不需要编译器到底该怎么做,你认为它会如果通过行执行的代码行。它可以根据“as-if”规则进行优化,这意味着如果可观察行为是相同的,它可以做更快的事情。

可观察行为不包括在调试器中运行代码。

变量task_从来没有任何可观察到的行为的任何后果,所以符合编译器可以完全优化它。函数add_task不会影响任何可观察的行为,因此符合标准的编译器可以完全优化它。

(我不确定它是否真的会这样做,但只是因为std::function可能必须进行动态分配,而当发生这种情况时,编译器就难以推断可观察到的副作用。)

而且,由于my_test没有任何东西被触动std::cin.get()的任何后果,如果它认为它可能走得更快的编译器就可以重新安排这两个语句。

如果您想要强制优化器按特定顺序执行某些操作,或者在特定时间提交特定内存内容,您应该执行下列操作:运行test_变量中的函数。

0

thx你的回答。 在影响,我运行调试版本和关闭所有优化,它发生为befor。 在错误的情况下,我插入TASK_()只是befor的std :: cin.get(),它会崩溃:

cccccccc() Unknown 
    [Frames below may be incorrect and/or missing] 
> tp_test.exe!add_task::__l3::<lambda>() Line 21 C++ 
    tp_test.exe!std::_Callable_obj<void <lambda>(void),0>::_ApplyX<void>() Line 284 C++ 
    tp_test.exe!std::_Func_impl<std::_Callable_obj<void <lambda>(void),0>,std::allocator<std::_Func_class<void> >,void>::_Do_call() Line 229 C++ 
    tp_test.exe!std::_Func_class<void>::operator()() Line 315 C++ 
    tp_test.exe!main() Line 39 C++ 
    tp_test.exe!__tmainCRTStartup() Line 626 C 
    tp_test.exe!mainCRTStartup() Line 466 C 
    kernel32.dll!765c8744() Unknown 
    ntdll.dll!__RtlUserThreadStart() Unknown 
    [email protected]() Unknown 

,所以我调试,断点TASK_(),按F11和拆卸,碰撞在文件“功能性”:

_Ret operator()(_Types... _Args) const 
     { // call through stored object 
00BE36A0 push  ebp 
00BE36A1 mov   ebp,esp 
00BE36A3 sub   esp,0CCh 
00BE36A9 push  ebx 
00BE36AA push  esi 
00BE36AB push  edi 
00BE36AC push  ecx 
00BE36AD lea   edi,[ebp-0CCh] 
00BE36B3 mov   ecx,33h 
00BE36B8 mov   eax,0CCCCCCCCh 
00BE36BD rep stos dword ptr es:[edi] 
00BE36BF pop   ecx  <==========crash 
00BE36C0 mov   dword ptr [this],ecx