在具有智能指针的类上正确实现复制构造函数和等于运算符

Posted

技术标签:

【中文标题】在具有智能指针的类上正确实现复制构造函数和等于运算符【英文标题】:Proper Implementation of Copy Constructor and Equals Operator on a class with smart pointers 【发布时间】:2014-09-13 10:35:04 【问题描述】:

假设我想实现一个可复制的类,那么我可以实现复制构造函数和赋值运算符。但是,唯一和共享指针变量的正确实现和处理是什么?请参阅这个具有两种类型指针的人为示例:

头文件

#include <memory>

using std::unique_ptr;
using std::shared_ptr;

class Copyable

private:
    unique_ptr<int> uniquePointer;
    shared_ptr<int> sharedPointer;

public:
    Copyable();
    Copyable(int value);
    Copyable(const Copyable& other);
    ~Copyable();

public:
    int GetUniqueValue()  return *uniquePointer; ;
    int GetSharedValue()  return *sharedPointer; ;
    Copyable& operator=(const Copyable& other);
;

CPP 文件

#include "stdafx.h"
#include "Copyable.h"

using namespace std;

Copyable::Copyable() : 
    uniquePointer(make_unique<int>()), sharedPointer(make_shared<int>())



Copyable::Copyable(int value) : 
    uniquePointer(make_unique<int>(value)), 
    sharedPointer(make_shared<int>(value))



Copyable::Copyable(const Copyable& other) : 
    uniquePointer(make_unique<int>(*other.uniquePointer)), 
    sharedPointer(make_shared<int>(*other.sharedPointer))
    // OR
    sharedPointer(other.sharedPointer)



Copyable::~Copyable()



Copyable& Copyable::operator=(const Copyable& other)

    if (&other != this)
    
        uniquePointer.reset();
        uniquePointer = make_unique<int>(*other.uniquePointer);

        sharedPointer = make_shared<int>(*other.sharedPointer);
        // OR
        sharedPointer = other.sharedPointer;
    

    return *this;

使用允许复制

Copyable copyable1(5);
int uniqueValue1 = copyable1.GetUniqueValue();
int sharedValue1 = copyable1.GetSharedValue();
Copyable copyable2 = copyable1;
int uniqueValue2 = copyable2.GetSharedValue();
int sharedValue2 = copyable2.GetSharedValue();

只有一种方法可以使用 make_unique 函数复制唯一指针,但是共享指针呢?我应该分配它还是使用 make_shared 函数?

更新 - 复制与移动

一个更广泛的说明我试图弄清楚什么时候使用什么。如果我决定使用复制,为什么要使用 unique_ptr?看来 shared_ptr 是要走的路。同样,如果使用移动语义,unique_ptr 似乎是要走的路。一般只说。我也许应该把它分成一个单独的问题。

【问题讨论】:

不,你不能复制一个唯一的指针,否则它就不是唯一的。跨度> 但是你可以复制它的内容不是吗?那么这是不好的做法吗? 是的,您可以复制它指向的内容,但不能复制实际的指针。此外,当您调用std::make_unique 函数时,它将调用std::unique_ptr constructor,并且构造函数采用另一个std::unique_ptr 对象转移指针的所有权 .最后一句话应该给你一个提示,告诉你应该如何看待新的智能指针,即在所有权方面。 unique_ptr 的全部意义在于,一个特定的unique_ptr 是指向给定对象的only 指针。当 unique_ptr 被销毁时,它将销毁该对象。因此,如果您以某种方式将unique_ptr 的值复制到另一个unique_ptr,那么当它们中的任何一个被销毁时,指向的对象也被销毁,现在unique_ptrs 之一指向已释放的内存并且您可能会导致释放后使用。 @RehanSaeed 恰恰相反;如果你想要你的类的只移动语义,你可以使用unique_ptr 成员;否则,您应该使用不同的指针工具。 【参考方案1】:

共享指针呢?我应该分配它还是使用 make_shared 函数?

tl;dr 该作业很可能是您要查找的内容。

这完全取决于所涉及的类的语义;

如果您希望对象共享shared_ptr 的状态,则需要分配或副本 如果您希望每个对象都保持自己的状态,则基于“其他”对象创建一个新的shared_ptr

如果它不需要共享状态,那么使用unique_ptr 真的会更好

作为一般的“经验法则”;

如果您的类型包含仅移动成员,则只允许移动。如果您的类型具有可复制成员,请允许复制。在有意义的地方,遵循“值”类型语义。争取“零法则”

【讨论】:

我明白了,所以在我的情况下应该对 shared_ptr 使用分配。但是复制与移动呢?作为一般规则,我想我现在明白如果使用 unique_ptr,请使用移动语义并禁止复制。 shared_ptr 呢,我可以应用一个通用规则吗? @RehanSaeed 复制语义。基本上shared_ptr 意味着与复制语义的共享状态;所有副本共享由share_ptr管理的同一对象

以上是关于在具有智能指针的类上正确实现复制构造函数和等于运算符的主要内容,如果未能解决你的问题,请参考以下文章

为对象指针实现复制构造函数和运算符的正确方法是啥

包含指向派生模板类的基类指针的类的赋值运算符和复制构造函数

指向具有私有构造函数的类的类成员的指针

在 C++ 中为具有包含指针的集合的类编写复制构造函数

c++中拷贝构造函数和赋值运算符重载本质上一样么

c++ 拷贝构造函数与赋值运算符重载函数的区别是