2013-10-07 7 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 

Почему движение лямбда зависит от того, было ли исходная переменная была сопзЬ или нет?

FWIW, MSVC2012 всегда делает две копии.

+0

Устойчивость не может быть отброшена автоматически. Добавляя его, захватывающая лямбда должна хранить его как const, и вы не можете перемещаться из const. –

+0

@ FrançoisMoisan это близко, но не совсем правильно, как вы можете видеть из моего примера, вы можете перегрузить конструктор перемещения с помощью 'const A &&' – aaronman

+0

@aaronman. Вы правы, конечно. Я почему-то подумал, что подпись запросила неконстантные ссылки rvalue-specfically. –

ответ

0

Поскольку у вас нет const A&& для вашего конструктора перемещения, он не будет вызываться. Поскольку перемещение обычно задает объект по умолчанию, вы часто не можете перемещаться из объекта const.

Помните, что если конструктор перемещения перегружен правильно, объект будет перемещен. Например, попробуйте запустить эту версию вашего кода.

#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 rvalue :-) Но мой вопрос: : константа переменной 'a' относится к типу переменной внутри лямбда? –

+0

@OlegAndreev хорошо, что его нужно хранить где-то вправо, конечно, чтобы действительно знать, что вы знаете немного больше о реализации папы баранины. – aaronman

+0

@OlegAndreev btw Я знаю, что у вас недостаточно репутации, но если мой ответ помог вам , вы все равно можете принять его – aaronman

Смежные вопросы