我正在考虑一个奇怪的用例,其中我想将对象移至nullptr。也许我应该给一个代码片段:
class Objpair {
public:
Objpair(Obj&& a, Obj&&b) : first(&a), second(&b) { }
private:
Obj* first;
Obj* second;
};
问题在于,当a和b超出范围时,第一个和第二个指针将悬空。如果我可以将Object a移到第一个指针上,那么应该就不会出现双重释放和作用域问题。如果首先将成员声明为Obj而不是Obj *指针,则直接的first(std :: move(a))将完成此工作。我在这里一定做错了。我正在考虑移动而不是复制,因为我试图将控制权从另一个对象转移到当前对象并提高性能。
使用指针版本是因为我正在考虑成员对象的多态行为。
答案 0 :(得分:5)
您可以做的是从您的参数中移动构造对象,如下所示:
class Objpair {
public:
Objpair(Obj&& a, Obj&& b)
: first(new Obj(std::move(a)))
, second(new Obj(std::move(b)))
{}
private:
Obj* first;
Obj* second;
};
我建议您使用std::unique_ptr
:
class Objpair {
public:
Objpair(Obj&& a, Obj&& b)
: first(std::make_unique<Obj>(std::move(a)))
, second(std::make_unique<Obj>(std::move(b)))
{}
private:
std::unique_ptr<Obj> first;
std::unique_ptr<Obj> second;
};
答案 1 :(得分:2)
您不能将对象移动到指针(nullptr或其他)上。也不能通过使指针指向对象来延长对象的生存时间-C ++根本无法那样工作。
由于需要多态行为,因此不能只复制构造或分配Obj
指针。您可能想要类似clone()
类Obj
的{{1}}方法,如本问题所述:
Copying derived entities using only base class pointers, (without exhaustive testing!) - C++
有关此的更多信息。不过请记住,您无法延长右值引用的寿命,因此必须以某种方式构造一个新对象。还记得避免内存泄漏。因此,如果您的clone()
产生了Obj*
,则需要编写如下内容:
class Objpair {
public:
Objpair(Obj&& a, Obj&&b) :
first(a.clone()),
second(b.clone())
{ }
private:
std::unique_ptr<Obj> first;
std::unique_ptr<Obj> second;
};
可能是std::shared_ptr
,而不是unique_ptr
(有关在两者之间进行选择,请参见this answer)。
如果您需要“多态”行为,但是您知道a和b在编译时的确切类型,并且您不介意拥有不同的ObjPair
类,则可以也尝试这样的事情:
template <typename T1, typename T2>
class Objpair {
public:
Objpair(T1&& a, T2&&b) : first(a), second(b)
{ }
private:
T1 first;
T2 second;
};
在这种情况下,不涉及任何指针(!)
答案 2 :(得分:2)
您在评论中说,
第一和第二个可以指向BaseClass,Derived1,Derived2,
在这种情况下,最好的选择是在virtual
中提供一个Obj
成员函数来克隆对象。
class Obj
{
public:
virtual Obj* clone() const = 0;
...
}
并使用它来初始化first
和second
。
class Objpair {
public:
Objpair(Obj&& a, Obj&&b) : first(a.clone()), second(b.clone()) { }
private:
Obj* first;
Obj* second;
};
,并确保您要在析构函数中分配由first
和second
指向的内存。有关更多详细信息,请参见The Rule of Three。
您可以使用智能指针消除类中用于管理对象寿命的代码的需求。使用std::unique_ptr
还是std::shared_ptr
取决于您希望使用Objpair
的方式。
答案 3 :(得分:0)
@Galik接受的答案很好。尽管它要求Obj
至少是可移动的,这与Clone()
解决方案的其他答案类似-它们都对Obj
及其子代提出了一些要求。要消除此限制,我们可以将Objpair
的构造函数更改为接受std::unique_ptr<Obj>
:
#include <memory>
class Obj
{
public:
Obj() {}
// non-copyable/non-movable
Obj(const Obj&) = delete;
Obj& operator=(const Obj&) = delete;
};
class Objpair {
public:
Objpair(std::unique_ptr<Obj>&& a, std::unique_ptr<Obj>&& b)
: first(std::move(a))
, second(std::move(b))
{}
private:
std::unique_ptr<Obj> first;
std::unique_ptr<Obj> second;
};
int main()
{
Objpair p{std::make_unique<Obj>(), std::make_unique<Obj>()};
return 0;
}
可能的奖金是:
a
和b
参数的实例多态传递给Objpair
。