2016-10-10 5 views
0
#include <iostream> 
#include <typeinfo> 

struct C { 
    explicit C() {std::cout << "constructor" << std::endl; } 
    C (const C&) { std::cout << "copyconstructor" << std::endl;} 
    ~C() { std::cout << "destructor" << std::endl; } 
}; 

int main(){ 
    C c1; 
    auto f = [c1](){c1;}; 
    std::cout << "leaving function scope" << std::endl; 
    return 0; 
} 

Составитель сПочему CopyConstructor вызывается с помощью Lambdas/Closures?

g++ -o a -std=c++11 test.cpp -fno-elide-constructors 

формирует выходной сигнал:

constructor copyconstructor copyconstructor destructor leaving function scope destructor destructor

Compiling с

g++ -o a -std=c++11 test.cpp 

генерируют выходной сигнал:

constructor copyconstructor leaving function scope destructor destructor

Так как я пропустил параметр компилятора -fno-elide-constructors во второй компиляции, почему сгенерированный код все еще вызывает CopyConstructor один раз? Я предположил, что g++ компилятора автоматически использовать копию Пропуск для инициализации auto f, как он сделал для инициализации закрытия, которая будет иметь результат:

constructor construtor leaving function scope destructor destructor

+1

'-fno-elide-constructors' не является оптимизацией. Это наоборот. – juanchopanza

+2

Вы просите компилятор сделать копию 'c1', когда вы запишете ее в лямбда, что вы ожидаете от нее в этом случае? – Praetorian

+0

'f' является копией' c1', поэтому должна быть задействована хотя бы одна копия. – juanchopanza

ответ

1

Я предположил, что г ++ компилятор будет автоматически использовать копию Пропуск для инициализации авто f, как это было сделано для инициализации укупорочного средства

Но для инициализации крышки не использовалось копирование. Одиноким copyconstructor вы видели было инициализация переменной закрытия. Это невозможно устранить. Даже в C++ 17; вы всегда будете иметь 2 объекта C, один из которых копируется из другого.

Если вы хотите, чтобы лямбда просто ссылалась на внешний объем, тогда вы должны были захватить переменную по ссылке: [&c1]. Захват по значению означает его копирование.

+0

Но почему он напечатал 2 раза 'copyconstructor', когда я использовал опцию' -fno-elide-constructors'? – SebNag

+2

@SebTu: Потому что 'auto f = prvalue', в pre C++ 17, означает сгенерировать это временное значение и использовать его для инициализации' f'. Таким образом, он будет делать копию/перемещение, если только оно не будет отменено. И вы остановили его в этом вопросе. –