c++ - 如何将对象的所有权传递给函数外部

标签 c++ c++11 move

是否有任何方法可以在堆栈内存中将函数中创建的对象的所有权传递给函数外部而不使用复制构造

通常,编译器会自动对函数栈上的对象调用析构。因此,如果我们想创建一个类的对象(可能带有一些特定的参数),我们如何避免浪费大量资源从临时对象复制?

这是一种常见的情况:

while(...){
    vectors.push_back(createObject( parameter ));
}

所以当我们想在迭代中用一些参数创建对象,并将它们压入vector时,正常的值传递方式会花费很多时间来复制对象. 我不想在堆内存上使用指针和new 对象,因为用户很可能会忘记删除 它们,从而导致内存泄漏

嗯,智能指针也许是一个解决方案。但是……不那么优雅,我想。呵呵

有没有办法应用右值引用 move 语义来解决这个问题?

最佳答案

通常,按值返回对象将不会复制对象,因为编译器应该进行(命名的)返回值优化,从而省略复制。

通过这种优化,返回对象的空间是从调用上下文(外部堆栈框架)分配的,并且对象是直接在那里构造的。

在您的示例中,编译器将在 createObject() 的上下文中为对象分配空间。叫做。由于此上下文是 std::vector<T>.push_back() 的(未命名)参数成员函数,这用作右值引用,因此 push_back()按值将通过将对象 move (而不是复制)到 vector 中来使用它。这是可能的,因为如果生成的对象是可 move 的。否则,将发生复制。

总而言之,每个对象都将被创建,然后 move (如果可 move )到 vector 中。

下面是一个示例代码,更详细地展示了这一点:

#include <iostream>
#include <string>
#include <vector>

using Params = std::vector<std::string>;

class Object
{
public:
    Object() = default;
    Object(const std::string& s) : s_{s}
    {
        std::cout << "ctor: " << s_ << std::endl;
    }
    ~Object()
    {
        std::cout << "dtor: " << s_ << std::endl;
    }

    // Explicitly no copy constructor!
    Object(const Object& other) = delete;

    Object(Object&& other)
    {
        std::swap(s_, other.s_);
        std::cout << "move: traded '" << s_ << "' for '" << other.s_ << "'" << std::endl;
    }

    Object& operator=(Object other)
    {
        std::swap(s_, other.s_);
        std::cout << "assign: " << s_ << std::endl;
        return *this;
    }

private:
    std::string s_;
};


using Objects = std::vector<Object>;

Object createObject(const std::string& s)
{
    Object o{s};
    return o;
}

int main ()
{
    Objects v;
    v.reserve(4);  // avoid moves, if initial capacity is too small
    std::cout << "capacity(v): " << v.capacity() << std::endl;

    Params ps = { "a", "bb", "ccc", "dddd" };

    for (auto p : ps) {
        v.push_back(createObject(p));
    }

    return 0;
}

请注意 class Object明确禁止复制。但要使其工作, move 构造函数必须可用。

关于何时可以(或将)发生复制省略的详细摘要可用 here .

关于c++ - 如何将对象的所有权传递给函数外部,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45712257/

相关文章:

c++ - 将可变参数列表插入 vector 中?

c++ - 没有 std::move 的右值引用

C++ 名称查找受模板方法声明的影响

c++ - 自定义QGraphicsPixmapItem不显示像素图

c++ - 序列容器-为什么只有几个序列容器才支持一些表达式

c++ - 如果我通过引用捕获局部变量并且超出范围会怎样?

c - 来自 fork 的 Pid 不为 0 或小于 0 (minix)

c++ - 在 std::thread 中使用 std::move

c++ - 指定 std::function 的默认值

c++ - C++中如何使用GC_malloc然后调用构造函数?