繁体   English   中英

了解函数返回的对象的移动语义

[英]Understanding move semantics with objects returned by a function

我从learncpp.com遇到了以下程序,作为理解移动语义的示例。 我试图运行此程序,并按照教程中的说明查看程序流程的工作方式。

但是,我无法在函数调用中理解它。

Auto_ptr4<Resource> generateResource()
{
    Auto_ptr4<Resource> res(new Resource);
    return res; // this return value will invoke the move constructor
}

曾经说过将使用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 ++标准的整个部分专门讨论此用例。

[class.copy.elision / 1.1]

在具有类返回类型的函数中的返回语句中,当表达式是非易失性自动对象的名称时(除了函数参数或由处理程序的异常声明引入的变量([except.handle] ))具有与函数返回类型相同的类型(忽略cv限定),可以通过将自动对象直接构造到函数调用的返回对象中来省略复制/移动操作

如果要防止省略,则需要返回一个不能合法删除的表达式。 幸运的是,在这种情况下也很容易强制调用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不会被忽略。

这对于学习目的是很好的,但是不要在实际代码中这样做。 复制省略是一件非常好的事情,可以使代码更高效。 让编译器在可能的时候为您完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM