Насколько я понимаю, конструктор перемещения вызывается, если он существует, когда мы возвращаем локальный объект из функции. Однако я столкнулся с ситуацией, когда вместо этого вызывался конструктор копирования, как показано в следующем примере в функции foo2()
. Почему это случилось?
#include <cstdio>
#include <memory>
#include <thread>
#include <chrono>
class tNode
{
public:
tNode(int b = 10)
{
a = b;
printf("a: %d, default constructor %s() is called at %s:%d \n", a, __func__, __FILE__, __LINE__);
}
tNode(const tNode& node)
{
a = node.a;
printf("a: %d, copy constructor %s() is called at %s:%d \n", a, __func__, __FILE__, __LINE__);
}
tNode& operator=(const tNode& node)
{
a = node.a;
printf("a: %d, copy assignment %s() is called at %s:%d \n", a, __func__, __FILE__, __LINE__);
}
tNode(tNode&& node)
{
a = node.a;
printf("a: %d, move constructor %s() is called at %s:%d \n", a, __func__, __FILE__, __LINE__);
}
tNode& operator=(tNode&& node)
{
a = node.a;
printf("a: %d, move assignment %s() is called at %s:%d \n", a, __func__, __FILE__, __LINE__);
}
~tNode() { printf("a: %d, destructor %s() is called at %s:%d \n", a, __func__, __FILE__, __LINE__); }
private:
int a = 0;
};
tNode foo()
{
tNode node;
return node;
}
tNode foo2()
{
std::unique_ptr<tNode> up = std::make_unique<tNode>(20);
return *up;
}
int main()
{
{
tNode n1 = foo();
tNode n2 = foo2();
}
// we pause here to watch how objects are created, copied/moved, and destroyed.
while (true)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
Приведенный выше код скомпилирован с g++ --std=c++17 -fno-elide-constructors
и вывод:
a: 10, default constructor tNode() is called at testCopyControl.cpp:13
a: 10, move constructor tNode() is called at testCopyControl.cpp:31
a: 10, destructor ~tNode() is called at testCopyControl.cpp:40
a: 10, move constructor tNode() is called at testCopyControl.cpp:31
a: 10, destructor ~tNode() is called at testCopyControl.cpp:40
a: 20, default constructor tNode() is called at testCopyControl.cpp:13
a: 20, copy constructor tNode() is called at testCopyControl.cpp:19
a: 20, destructor ~tNode() is called at testCopyControl.cpp:40
a: 20, move constructor tNode() is called at testCopyControl.cpp:31
a: 20, destructor ~tNode() is called at testCopyControl.cpp:40
a: 20, destructor ~tNode() is called at testCopyControl.cpp:40
a: 10, destructor ~tNode() is called at testCopyControl.cpp:40
Из выходных данных мы знаем, что конструктор копирования вызывается, когда foo2()
возвращает *up
для инициализации временного tNode
объекта; почему не был вызван конструктор перемещения?