具有unique_ptr数据成员的用户定义类型的重载运算符=

时间:2018-10-24 02:59:39

标签: c++ operator-overloading smart-pointers

我有一个用户定义的类,该类具有一个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引用?

2 个答案:

答案 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.ptrb.ptr指向完全相同的对象(即存储相同的指针),请使用共享指针。在这种情况下,您绝对不应使用唯一的指针,因为调用ab的析构函数会破坏指向的对象,从而使ab处于无效状态州。

如果您希望在调用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;
}