可以将右值移入 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
是否可以将 '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