我有一个用户定义的类,该类具有一个std::unique_ptr
成员。我试图使赋值运算符重载,以向unique_ptr
成员添加相同类型的对象,或将值赋给ptr
值。
class object
{
public:
// POD types
object& operator=(const object& _obj);
std::unique_ptr<baseClass> ptr;
}
我尝试使用:
std::unique_ptr::swap()
但是交换函数是非常量的,因此我尝试分配以下结果:
std::unique_ptr::get()
转到ptr
,然后致电:
std::unique_ptr::release()
但是release也是非const的,因此我不能保证ptr
会被正确地破坏,因为旧的ptr
仍将拥有所有权。 las,operator=()
的{{1}}不接受对另一个unique_ptr
的非常量引用,因此我选择对我的班级使用operator =。
unique_ptr
然后稍后调用object& object::operator=(const object& _obj)
{
//POD types use operator= as normal
ptr.reset(nullptr);
return *this;
}
方法来设置setPtr()
。我只想检测类型并使用以下方法分配ptr
:
ptr
但是整个Stack Overflow和我首选的搜索引擎的共识是,检测这样的类型将是设计缺陷。我的问题是:我是否忽略了一些简单的问题,是否有更好的方法来重载具有ptr.reset(new detectedType );
成员的用户定义类型的赋值运算符?
编辑前:
我将参数更改为unique_ptr
而不是object&
,它起作用了。这是解决此问题的好方法,还是我应该仅尝试对其他类的const引用?
答案 0 :(得分:1)
我的问题是:我是否忽略了一些简单的东西,是否有更好的方法来重载具有unique_ptr成员的用户定义类型的赋值运算符?
确实有。这分解为了解C++
中的智能指针的作用。如果您的对象只有一个引用,那么通常使用std::unique_ptr
。这就是std_unique_ptr
既不可复制构造也不可复制分配的原因。如果您使用std::unique_ptr
按照帖子中的描述手动创建ptr.get()
的两个副本,则最终将处于无效状态,因为一旦一个副本离开范围,std::unique_ptr
析构函数还将破坏它指向的对象,使另一个std::unqiue_ptr
处于无效状态(它指向已释放的内存位置)。因此,如果可能对您的对象有多个引用,则应该改用std::shared_ptr
。
在您的示例中,问题是您想要实现什么?
如果希望您的赋值运算符在调用a = b
之后,a.ptr
和b.ptr
指向完全相同的对象(即存储相同的指针),请使用共享指针。在这种情况下,您绝对不应使用唯一的指针,因为调用a
或b
的析构函数会破坏指向的对象,从而使a
或b
处于无效状态州。
如果您希望在调用a = b
之后,a.ptr
指向*(b.ptr)
的独立副本,则确实可以使用唯一的指针并像这样实现您的赋值运算符(提供{{1} }是可复制的):
baseClass
但是请注意,这仅在object& object::operator=(const object& _obj)
{
//POD types use operator= as normal
ptr.reset(new baseClass(*_obj.ptr));
return *this;
}
为baseClass
(不太可能考虑名称...)的情况下有效,即final
不会存储指向派生类对象的指针。否则,将导致BenVoigt指出的slicing。
最后,通常希望调用ptr
不会不会更改a = b
。因此,使b
成员可变并使用ptr
对我来说是个坏主意。如果您出于性能(或其他方面)方面的考虑要实现此行为,我建议改为实施移动分配运算符
swap
并调用object& object::operator=(object&& _obj)
{
//POD types use operator= as normal
ptr = std::move(_obj.ptr);
return *this;
}
,这清楚地表明a = std::move(b)
可能会处于不同的状态。
答案 1 :(得分:0)
这是mutable
关键字的好用例。如果将ptr
声明为mutable
,则表明即使类的实例在语义上是常量,它也必须对特定数据成员执行非常量操作。声明您的类,如下所示,您应该能够实现使用swap
的原始想法:
class object
{
public:
// POD types
object& operator=(const object& _obj);
mutable std::unique_ptr<baseClass> ptr;
}