[C++0x] Move semantics + NRVO
Bonjour les développeurs,
Soit le code suivant :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
#include <iostream>
class movable
{
public:
movable(int){}
movable(const movable&) = delete;
movable(movable&&)
{
std::cout << "move\n";
}
const movable&
operator=(const movable&) = delete;
const movable&
operator=(movable&&) = delete;
};
movable
f()
{
return movable(0);
}
int
main()
{
std::cout << "test1:\n";
movable o1 = f();
std::cout << "test2:\n";
movable o2(f());
std::cout << "test3:\n";
movable o3(std::move(f()));
return 0;
} |
On a une classe non copiable mais movable et une fonction qui renvoie un objet de cette classe. Dans le main(), j'effectue trois appels à cette fonction, en effectuant respectivement une assignation par copie, une construction par copie et une construction par mouvement.
Sachant que j'ai désactivé la construction par copie et l'opérateur d'assignation, je m'attends à ce que le compilateur refuse les tests 1 et 2. Seulement non, aucun problème de compilation.
Étant donné que j'ai la sortie suivante, j'imagine que c'est la NRVO qui permet ce comportement :
Code:
1 2 3 4 5
|
test1:
test2:
test3:
move |
Si je désactive la NRVO (-fno-elide-constructors), des déplacements sont effectués dans tous les cas :
Code:
1 2 3 4 5 6 7 8 9 10
|
test1:
move
move
test2:
move
move
test3:
move
move |
On a donc un code qui compile seulement dans le cas où le compilateur supporte la NRVO.
C'est pas un peu discutable comme comportement ? À moins que cette optimisation ait été prise en compte dans le nouveau standard ?
J'hésite à remonter ce comportement comme un bug. Vous en pensez quoi ?
Voici le Makefile pour ceux qui veulent tester (GCC 4.4 requis) :
Code:
1 2 3
|
test: main.cpp
g++-4.4 -o test main.cpp -W -Wall -ansi -pedantic -std=c++0x -fno-elide-constructors |