2017-08-12 4 views
2
#include <iostream> 
using namespace std; 

class A { 
public: 
    A() { 
     cout << "A()" << endl; 
    } 
    A(const A& a) { 
     cout << "A(const A& a)" << endl; 
    } 
    A(A&& a) { 
     cout << "A(A&& a)" << endl; 
    } 
    A& operator=(const A& a) { 
     cout << "operator=(const A& a)" << endl; 
     return *this; 
    } 
    A& operator=(A&& a) { 
     cout << "operator=(A&& a)" << endl; 
     return *this; 
    } 
    ~A() { 
     cout << "~A()" << endl; 
    }; 
}; 

A foo() { 
    A a; 
    return a; 
} 

int main() { 
    A a = foo(); 
} 

Compile:Construction et Destructing de la variable variable locale et retour en C++

clang++ test.cpp -o test -std=c++11 

Sortie:

A() 
~A() 

Pourquoi il y a juste une paire de A() et ~ A() dans la sortie?

Pourquoi le constructeur de déplacement n'est pas appelé?

Le compilateur a-t-il effectué une optimisation du code?

Répondre

6

Le constructeur Move (ou Copy) n'est pas appelé en raison de Copy Elision. La variable locale construite par le compilateur dans l'emplacement de la valeur de retour directement. Ces optimisations sont également appelées RVO (Return Value Optimization).

Il existe certaines conditions pour que le compilateur autorise de telles optimisations et elles sont mentionnées dans la norme. Mais il peut plus commode de citer l'article 25 de Effective Modern C++ by Scott Meyers concernant ces conditions (pas d'informations rigoureuses que dans la norme, mais peut-être plus efficace pour absorber):

paraphrasant la prose légaliste (sans doute toxiques) de la norme, [ ...] les compilateurs peuvent éviter la copie (ou le déplacement) d'un objet local dans une fonction qui retourne par valeur si (1) le type de l'objet local est le même que celui retourné par la fonction et (2) l'objet local est ce qui est retourné.