2013-10-07 51 views
1

當用gcc 4.7.2或4.8.1編譯和運行下面的程序複製構造呼籲捕獲變量,而不是移動構造函數

#include <stdio.h> 
#include <functional> 

class A 
{ 
public: 
    A() 
    { 
    } 
    A(const A& a) 
    { 
     printf("Copy ctor\n"); 
    } 
    A(A&& a) 
    { 
     printf("Move ctor\n"); 
    } 
}; 

int main() 
{ 
    A a; 
    auto func = [a] { 
    }; 

    auto newfunc = std::move(func); 
    return 0; 
} 

會給輸出:

Copy ctor 
Move ctor 

這似乎完全正常。

然而,當A a;更改爲const A a;,輸出如下:

Copy ctor 
Copy ctor 

爲什麼拉姆達的舉動受到了事實上的原始變量是否已經const或不?

FWIW,MSVC2012總是製作兩份。

+0

constness不能自動刪除。通過添加它,捕獲lambda必須將其存儲爲const,並且不能從const移動。 –

+0

@FrançoisMoisan這是接近但不完全正確,正如你可以從我的例子看到的,你可以用'const A &&' – aaronman

+0

@aaronman重載移動構造函數你當然是對的。我以某種方式認爲簽名要求非const const rvalue引用specfically。 –

回答

0

由於您的移動構造函數沒有const A&&,因此不會調用它。由於移動通常會將對象設置爲默認值,因此您通常無法從常量對象移動。

請記住,如果移動構造函數正確重載,對象將被移動。例如,嘗試運行此版本的代碼。

#include <stdio.h>                 
#include <functional>                

class A                    
{                     
public:                    
    A()                    
    {                    
    }                    
    A(const A& a)                 
    {                    
     printf("Copy ctor\n");              
    }                    
    A(const A&& a)                 
    {                    
     printf("Move ctor\n");              
    }                    
};                     

int main()                   
{                     
    const A a;                  
    auto func = [a] {                
    };                    

    const auto newfunc = std::move(func);           
    return 0;                  
} 

運行這段代碼,你會注意到,對象移動羯羊存在const合格與否。

+0

謝謝,今天我瞭解了const的右值引用:-)但是我的問題是:'a'變量的常量是否與lambda中的變量類型有關? –

+0

@OlegAndreev好吧,它必須存儲在正確的位置,當然要真正知道你會更多地瞭解有關羔羊爸爸實施 – aaronman

+0

@OlegAndreev btw我知道你沒有足夠的代表upvote,但如果我的回答幫助你,你仍然可以接受它 – aaronman