检查char指针是否为null - 复制构造函数

时间:2015-02-09 02:17:52

标签: c++ constructor initialization copy-constructor

我正在处理以下代码

class base
{
private:
    char* mycharpointer;
    std::string mystring;

public:
    base() : mycharpointer(NULL) {/*default constructor*/}

    //Copy Constructor
    base(const base& rhs){
        if(mycharpointer != NULL)  ---> Why is this condition true ?
        {
            mycharpointer = new char[ strlen(rhs.mycharpointer + 1)];
            strcpy(this->mycharpointer,rhs.mycharpointer);
        }
        mystring = rhs.mystring;
    }


    base operator=(base& b)
    {   
        if(this == &b) 
            return *this;

        base temp(b); 
        temp.swap(*this);
        return *this;
    }

    //Swap operation
    void swap(base& lhs) {
        std::swap(lhs.mycharpointer,this->mycharpointer);
        std::swap(lhs.mystring,this->mystring);
    }

    //Destructor
    virtual ~base(){
        if(mycharpointer) 
            delete[] mycharpointer;
    }
};

class der : public base
{
public:
    char* mycharpointer_der;
    std::string mystring_der;
    foo* f;

public:
    der():mycharpointer_der(NULL)
    {
    }


    der(const der& rhs) : base(rhs) 
    {
        if(mycharpointer_der) 
        {   
            mycharpointer_der = new char[ strlen(rhs.mycharpointer_der + 1)];
            strcpy(this->mycharpointer_der,rhs.mycharpointer_der); 
        }
        mystring_der = rhs.mystring_der;
        f = new foo(*rhs.f);
    }


    der& operator=(der& d)
    {   
        if(this == &d) //Make sure its not the same class
            return *this;

        base::operator= (d);
        der temp(d); 
        temp.swap(*this);
        return *this;
    }

    //Swap operation
    void swap(der& lhs) {
        std::swap(lhs.mycharpointer_der,this->mycharpointer_der);
        std::swap(lhs.mystring_der,this->mystring_der);
    }

    virtual ~der(){
         if(mycharpointer_der) //Necessary check as to make sure you are not deleting a NULL address otherwise exception thrown.
            delete[] mycharpointer_der;
    }

};



int main()
{
    der d;
    d.mycharpointer_der = "Hello World";
    d.mystring_der = "Hello String";
    der b;
    b = d;
}

现在在上面的代码中调用了d的复制赋值运算符。反过来调用基类的复制赋值运算符。在基类的复制赋值运算符中,调用基类的复制构造函数。我的问题是为什么条件

if(mycharpointer != NULL)  
基类中的

是真的吗?即使我在基类的初始化列表中明确地为它指定了一个NULL。

3 个答案:

答案 0 :(得分:6)

那个检查很荒谬。在构造时,当我们进入正文时,mycharpointer被默认初始化并且将包含一些垃圾值,可能0但可能不会。

那说,如果rhs.mycharpointer为NULL,会发生什么?然后strlen调用将失败。这是您需要检查其值的charpointer

base(const base& rhs)
{
    if (rhs.mycharpointer) {
        mycharpointer = new char[ strlen(rhs.mycharpointer) + 1 ]; 
        //                         outside the parens      ^^^^
        strcpy(this->mycharpointer,rhs.mycharpointer);
    }
    else {
        mycharpointer = NULL;
    }
    mystring = rhs.mystring;
}

或者,由于您已经在使用string,我们也可以继续string使用mycharpointer。这有一个额外的好处,我们甚至不必编写复制构造函数,正如您所见,它可能容易出错:

base(const base& ) = default;

答案 1 :(得分:1)

C ++编译器只确保全局变量和静态变量将被初始化,所以在这种情况下,mycharpointer实际上可能指向一些无用的垃圾(悬空指针)

base(const base& rhs){
        if(mycharpointer != NULL)  ---> Why is this condition true ?
        {
            mycharpointer = new char[ strlen(rhs.mycharpointer + 1)];
            strcpy(this->mycharpointer,rhs.mycharpointer);
        }
        mystring = rhs.mystring;
    }

因为mycharpointer实际上指向堆上分配的数据,所以如果要重新定位它,则需要首先释放现有数据。    类似的东西:

    if ( mycharpointer)  {
        delete [] mycharpointer;
}

答案 2 :(得分:0)

显然你期望在复制构造函数之前运行默认构造函数。

但它不会。