[C++0x] std::move(), rvalue reference et comparses
Bonjour,
On a beau �tre pointu sur certains sujets, il est est d'autres qui r�sistent � notre mani�re d'appr�hender les choses. Sur une grosse partie du futur standard, je n'ai aucun probl�me de compr�hension. Mais sur les rvalue references, je cale tr�s nettement.
Ceci �tant dit, j'en viens � mon probl�me. A toutes fins utiles, voici une information d'importance :
Code:
1 2 3 4 5 6 7
|
edt@desktop:~/ddcomp$ g++ -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) |
Bien. J'essaie d'impl�menter une surcouche � libxml2 qui corresponde � mes besoins. J'en viens au code de la classe xml::document :
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
|
namespace xml {
document&& read_xml_file(const std::string& path)
{
xmlDocPtr xmldoc = xmlReadFile(path.c_str(), NULL, 0);
if (xmldoc)
{
return std::move(document(xmldoc));
}
std::stringstream stream;
stream << "cannot parse '" << path << "' as an XML file";
throw std::invalid_argument(stream.str());
}
document::document(xmlDocPtr xmldoc)
: m_doc(xmldoc)
{
}
document::document(document&& other)
: m_doc(other.m_doc)
{
other.m_doc = nullptr;
}
document::~document()
{
if (m_doc)
{
xmlFreeDoc(m_doc);
}
}
} |
(nullptr, n'�tant aps encore reconnu par g++ 4.4, est en fait un simple #define nullptr 0; �a n'a pas d'importance dans notre cas, mais �a peut en avoir si vous avez envie de compiler le code).
Ce code est ainsi utilis� :
Code:
1 2 3 4
|
{
xml::document d = xml::read_xml_file(path_to_file);
} |
Dans mon esprit, les choses suivantes devraient se passer :
1) cr�ation d'une instance de xml::document()
2) transformation de cette instance en rvalue reference (gr�ce � std::move)
3) appel du move constructor, et donc �change des valeurs de pointeur xmlDocPtr (NULL contre un pointeur valide)
4) destruction de la rvalue reference, qui contient un nullptr (donc le destructeur ne fait pas grand chose)
5) destruction de l'instance "d"
C'est probablement l� (dans mon esprit, je veux dire) que le b�t blesse. Parce que les choses ne se passent pas du tout comme �a. A la place, le constructeur prenant une rvalue ref n'est jamais appel�, donc l'�change ne se passe jamais, et les deux instances existantes (la temporaire et celle qui est r�ellement utilis�e) poss�dent le m�me pointeur. Bien evidemement, un probl�me se pose lors de la destruction : xmlFreeDoc() plante, lamentablement, parce que le pointeur est lib�r� deux fois.
Ce n'est pas ce qui �tait pr�vu dans mon esprit tortur�.
Est-ce que l'un de vous pourrait me pointer mon erreur - de raisonnement, de code, etc - et (bonus accord� sous la forme de mon �ternelle gratitude) m'expliquer ce que visiblement, je n'ai pas compris (et comme je ne l'ai pas compris, je ne sais m�me pas ce que c'est) ?
Merci d'avance !