可以将右值移入 shared_ptr

Can an rvalue be moved into a shared_ptr

是否可以将 'move' 一个 rvalue 变成 shared_ptr。到目前为止我尝试过的所有方法都会产生一个副本。

我想要的使用模式是:

class Element {
public:
    Element(const string &);
    Element(const Element &) = delete; //delete copy constructor
    // ...
};

class MyCollectionOfElements {
public:
    void add(Element &&); // add by rvalue
    // ...
protected:
    vector<shared_ptr<Element>> elements;
};

MyCollectionOfElements elements;
elements.add(Element("something"));

我想要这种模式是有原因的,并且知道有其他模式自然有效(例如,将新的 Element 作为指针而不是 rvalue 传递)。

我目前的怀疑是传入的 rvalue 在堆栈上,而我需要将它放在堆上以将其存储在 shared_ptr 中,因此复制是不可避免的。

是:

void add(Element && e)
{
    elements.push_back(std::make_shared<Element>(std::move(e)));
}

您还必须确保您的 class 实际上 具有 移动构造函数:

class Element
{
public:
    Element(Element &&) = default;
    // ...
};

通过声明复制构造函数,您禁止隐式声明移动构造函数,因此您需要显式声明它。

我猜你误解了运动语义的概念。您必须将指针传递给智能指针,指针可以是任何类型 - lvalue/rvalue

    void f(A *&&p) {}

接受指向 A 的指针的右值引用的函数;但 p 仍然是左值,它具有指向指针的右值引用类型, 所以你必须 "cast"(std::move - 什么都不做只是将左值转换为右值) std::shared_ptr(std::move(p));

    A *g() { return new A;}
    A *a;
    f(a);//error        
    f(g());//works fine
    f(new A());//also fine