我应该删除运营商分配功能中的原点指针吗?

时间:2016-01-05 13:55:11

标签: c++ copy-constructor assignment-operator

我已经编写了以下演示代码来学习复制构造函数和赋值运算符。然而有一点混乱。有人告诉我删除赋值运算符中的指针并为data分配新地址。但是我只能让我的代码工作删除该行。我已将this页面作为参考,但它仅显示int的示例而不是int*。我该如何解决这个问题?

#include <iostream>
#include <string>
#include <vector>
#include <random>
#include <boost/smart_ptr.hpp>
#include <boost/make_shared.hpp>

using namespace boost;

class ClassOne
{
public:
    ClassOne():data(NULL) {}
    ClassOne(int data_param):data(NULL)
    {
        init(data_param);
        std::cout << "construct" << std::endl;
    }

    virtual ~ClassOne()
    {
        if (data) {
            delete data;
        }
        data = NULL;
    }

    ClassOne(const ClassOne& rhs){
        std::cout<< "copy " <<std::endl;
        data = NULL;
        init(*rhs.data);
    }

    ClassOne& operator = (const ClassOne& rhs){
        std::cout<< "assign " <<std::endl;
        int* p_old = rhs.data;
        data = new int(*p_old);
        //delete p_old;            // I have to delete this line to make my code work
        return *this;
    }

    void init(int data_param)
    {
        if (data) {
            delete data;
        }
        data = new int(data_param);
    }

private:
    int* data;
};

int main(int argc, const char * argv[]) {
    ClassOne c1(10);
    ClassOne c2(c1);       // call copy constructor
    ClassOne c3;
    c3 = c1;               // call assignment function
    return 0;
}

2 个答案:

答案 0 :(得分:2)

当您打算删除自己的(data)对象的当前this成员时,您正尝试删除其他对象的data成员。您可能想要的是:

ClassOne& operator = (const ClassOne& rhs){
    std::cout<< "assign " <<std::endl;
    delete data;               // delete your own old data
    data = new int(*rhs.data); // clone the rhs's data
    return *this;
}

答案 1 :(得分:0)

您的代码失败是因为您正在双重删除某些内容:您删除了复制赋值和析构函数中的指针。删除指针不会使其为空,这就是它在析构函数中传递if的原因。 (顺便说一下,在删除之前你不需要将指针检查为null,delete无论如何都要进行检查)

我建议复制赋值不要改变rhs变量,因为删除data指针很容易导致内存访问。我宁愿实现一个移动构造函数和赋值来使这个行为显式化。我会删除复制构造函数和赋值并添加这些函数:

ClassOne(const ClassOne&) = delete;
ClassOne& operator=(const ClassOne&) = delete;

ClassOne(ClassOne&& rhs) {
    std::swap(data, rhs.data);
}

ClassOne& operator=(ClassOne&& rhs) {
    std::swap(data, rhs.data);
}

这需要在分配时调用std::move

或者,您可以实现非窃取复制构造函数。这将要求您深度复制数据指针(复制内容而不是指针)

ClassOne(const ClassOne& rhs) {
    if (!data) {
        data = new int;
    }
    *data = *(rhs.data);
}

ClassOne& operator=(const ClassOne& rhs) {
    if (!data) {
        data = new int;
    }
    *data = *(rhs.data);
}