简体   繁体   English

智能指针如何影响 5 规则?

[英]How do smart pointers affect the rule of 5?

I've learnt that when you use pointers in a class, you should implement the rule of 5. If you do not use pointers then you're okay, and in fact its preferable, to use the defaults.我了解到,当您在 class 中使用指针时,您应该执行 5 规则。如果您不使用指针,那么您可以,实际上更可取的是使用默认值。 However, how does this work with smart pointers?但是,这如何与智能指针一起使用? For example a class containing an int* might look like this:例如,包含int*的 class 可能如下所示:

class A {
private:
    int *num_;
public:

    explicit A(int* num) : num_(num) {}

    ~A() {
        delete num_;
    }

    A(const A &other) {
        if (this != &other) {
            num_ = other.num_;
        }
    }

    A(A &&other) noexcept {
        if (this != &other) {
            num_ = other.num_;
        }
    }

    A &operator=(A &other) {
        if (this == &other) {
            this->num_ = other.num_;
        }
        return *this;
    }

    A &operator=(A &&other) noexcept {
        if (this == &other) {
            this->num_ = other.num_;
        }
        return *this;
    };


};

But if we use smart pointers, is it sufficient to just do this?但是如果我们使用智能指针,这样做就足够了吗?

class B {
private:
    std::unique_ptr<int> num_;

public:

    explicit B(int num) : num_(std::make_unique<int>(num)) {};

};

Yes that is sufficent.是的,这就足够了。 The unique pointer does manage the memory.唯一指针确实管理 memory。 However, your two classes will behave differently because std::unique_ptr cannot be copied, hence there will be no compiler generated copy constructor nor assignment for B .但是,您的两个类的行为会有所不同,因为std::unique_ptr无法复制,因此不会有编译器生成的复制构造函数,也不会为B赋值。

Also note that you implemented all methods for the rule of 5, but not correctly.另请注意,您实现了规则 5 的所有方法,但不正确。 As mentioned in a comment, copying an A will result in two instances having the same pointer and delete it upon destruction.如评论中所述,复制A将导致两个实例具有相同的指针并在销毁时将其删除。 Actually getting this right is the whole point about the rule of 3/5 and why you should prefer the rule of 0.实际上,做到这一点是关于 3/5 规则的全部意义,以及为什么你应该更喜欢 0 规则。

If you use smart pointer (or any of the std:: containers) the class default destructor will call the destructor of the smart pointer (and containers).如果您使用智能指针(或任何 std:: 容器),class 默认析构函数将调用智能指针(和容器)的析构函数。 More on this topic here: Why doesn't the C++ default destructor destroy my objects?有关此主题的更多信息: 为什么 C++ 默认析构函数不破坏我的对象?

Those have different behaviour.那些有不同的行为。 A can be copied, B can only be moved. A可以复制, B只能移动。

NB your implementation of A is unsafe, it can lead to leaks and undefined behaviour.注意您的A实现是不安全的,它可能导致泄漏和未定义的行为。

A comparison of like-for-like would either delete A 's copy同类比较会delete A的副本

class A {
private:
    int *num_;
public:

    explicit A(int num) : num_(new int(num)) {}

    ~A() {
        delete num_;
    }

    A(const A &other) = delete;

    A(A &&other) noexcept 
     : num_(std::exchange(other.num, nullptr)) {}

    A &operator=(const A &other) =delete;

    A &operator=(A &&other) noexcept {
        swap(num_, other.num_);
        return *this;
    };
};

class B {
private:
    std::unique_ptr<int> num_;

public:

    explicit B(int num) : num_(std::make_unique<int>(num)) {};

};

Or define B 's copy或者定义B的副本

class A {
private:
    int *num_;
public:

    explicit A(int num) : num_(new int(num)) {}

    ~A() {
        delete num_;
    }

    A(const A &other) 
     : A(other.num) {}

    A(A &&other) noexcept 
     : num_(std::exchange(other.num, nullptr)) {}

    A &operator=(const A &other) {
        *num_ = *other.num;
        return *this;
    }

    A &operator=(A &&other) noexcept {
        swap(num_, other.num_);
        return *this;
    };
};

class B {
private:
    std::unique_ptr<int> num_;

public:

    explicit B(int num) : num_(std::make_unique<int>(num)) {};
    ~B() = default;
    B(const B & other) : B(*other.num_) {}
    B(B && other) = default;
    B& operator=(const B & other) { *num_ = *other.num_ }
    B& operator=(B && other) = default;

};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM