我从 learncpp.com 看到以下程序作为理解 move 语义的示例。我试着运行这个程序,看看程序流程是如何按照教程中的解释工作的。
但是,我在函数调用中无法理解它。
Auto_ptr4<Resource> generateResource()
{
Auto_ptr4<Resource> res(new Resource);
return res; // this return value will invoke the move constructor
}
据说会使用 move 构造函数,但当我设置断点和调试时它根本没有这样做。
谁能帮我理解为什么这里不调用 move 构造函数?编译器是否在这里省略?如果是这样,如何修改它以便调用 move 构造函数。请解释这里发生了什么。
此外,如果您能分享一些调用 move 构造函数的位置以及如何使用 move 构造函数代替复制构造函数的示例,那就太好了。
#include <iostream>
template<class T>
class Auto_ptr4
{
T* m_ptr;
public:
Auto_ptr4(T* ptr = nullptr)
:m_ptr(ptr)
{
}
~Auto_ptr4()
{
delete m_ptr;
}
// Copy constructor
// Do deep copy of a.m_ptr to m_ptr
Auto_ptr4(const Auto_ptr4& a)
{
m_ptr = new T;
*m_ptr = *a.m_ptr;
}
// Move constructor
// Transfer ownership of a.m_mptr to m_ptr
Auto_ptr4(Auto_ptr4&& a)
: m_ptr(a.m_ptr)
{
a.m_ptr = nullptr;
}
// Copy assignment
// Do deep copy of a.m_ptr to m_ptr
Auto_ptr4& operator=(const Auto_ptr4& a)
{
// Self-assignment detection
if (&a == this)
return *this;
// Release any resource we're holding
delete m_ptr;
// Copy the resource
m_ptr = new T;
*m_ptr = *a.m_ptr;
return *this;
}
// Move assignment
// Transfer ownership of a.m_ptr to m_ptr
Auto_ptr4& operator=(Auto_ptr4&& a)
{
// Self-assignment detection
if (&a == this)
return *this;
// Release any resource we're holding
delete m_ptr;
// Transfer ownership of a.m_ptr to m_ptr
m_ptr = a.m_ptr;
a.m_ptr = nullptr;
return *this;
}
T& operator*() const { return *m_ptr; }
T* operator->() const { return m_ptr; }
bool isNull() const { return m_ptr == nullptr; }
};
class Resource
{
public:
Resource() { std::cout << "Resource acquired\n"; }
~Resource() { std::cout << "Resource destroyed\n"; }
};
Auto_ptr4<Resource> generateResource()
{
Auto_ptr4<Resource> res(new Resource);
return res; // this return value will invoke the move constructor
}
int main()
{
Auto_ptr4<Resource> mainres;
mainres = generateResource(); // this assignment will invoke the move assignment
return 0;
}
谢谢
最佳答案
Auto_ptr4<Resource> generateResource()
{
Auto_ptr4<Resource> res(new Resource);
return res; // this return value will invoke the move constructor
}
您的代码是以一种非常允许复制省略的方式编写的。 C++ 标准有一整节专门讨论这个用例。
in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function parameter or a variable introduced by the exception-declaration of a handler ([except.handle])) with the same type (ignoring cv-qualification) as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function call's return object
如果要防止省略,需要返回一个不能被合法省略的表达式。幸运的是,在这种情况下也很容易强制调用 move 构造函数:
Auto_ptr4<Resource> generateResource()
{
Auto_ptr4<Resource> res(new Resource);
return std::move(res); // this return value will invoke the move constructor
}
因为现在表达式不是自动变量名,Auto_ptr4<Resource>&&
也不是。与 Auto_ptr4<Resource>
完全相同. c'tor 没有被省略。
这对于学习目的来说很好,但不要在实际代码中这样做。复制省略是一件非常好的事情,可以提高代码的效率。让编译器尽可能为您完成。
关于c++ - 了解函数返回的对象的 move 语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44922222/