c ++深层复制构造函数

时间:2017-11-15 05:13:59

标签: c++ copy-constructor deep-copy

这是我的代码:

#include<iostream>
#include<cstring>
using namespace std;

class String
{
private:
    char *s;
    int size;
public:
    String(const char *str = NULL); // constructor
    String& operator=(String &c){
        size = strlen(c.s);
        s = new char[size+1];
        strcpy(s, c.s);
    }
    ~String() { delete [] s; }// destructor
    void print() { cout << s << endl; }
    void change(const char *); // Function to change
};

String::String(const char *str)
{
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}

void String::change(const char *str)
{
    delete [] s;
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}

int main()
{
    String str1("learnc++");
    String str2 = str1;

    str1.print(); // what is printed ?
    str2.print();

    str2.change("learnjava");

    str1.print(); // what is printed now ?
    str2.print();
    return 0;
}

可以编译,结果是:

learnc++ 
learnc++ 
learnjava 
learnjava

除此之外,还有:

*** Error in `./code': double free or corruption (fasttop): 0x0000000000f7f010 ***

BTY,如果我删除“delete [] s;”在String :: change中,结果变为:

learnc++
learnc++
learnc++
learnjava

没有错误,为什么? 代码来自geek foe feeks,我更改了一些字符串,代码可以在其IDE中运行,但在我的ubuntu 14.04中,它不能。

2 个答案:

答案 0 :(得分:3)

您的班级没有关注Rule of Three,因为它缺少正确的复制构造函数。

String str2 = str1;只是String str2(str1);的语法糖,所以它使用了复制构造函数,而不是你的operator=(它有内存泄漏,BTW)。

由于您没有提供复制构造函数,编译器会为您提供一个,但它不会复制char*数据。它只是复制指针本身,这会导致你看到的行为。

正确的实现看起来更像是这样:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

class String
{
private:
    char *s;
    int size;
public:
    String(const char *str = NULL);
    String(const String &src);
    ~String();
    String& operator=(const String &rhs);
    void print() const;
};

String::String(const char *str)
{
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}

String::String(const String &src)
{
    size = src.size;
    s = new char[size+1];
    strcpy(s, src.s);
}

String::~String()
{
    delete [] s;
} 

void String::print() const
{
    cout << s << endl;
}

String& String::operator=(const String &rhs)
{
    if (&rhs != this)
    {
        String tmp(rhs);
        swap(s, tmp.s);
        swap(size, tmp.size);
    }
    return *this;
}

int main()
{
    String str1("learnc++");
    String str2 = str1;

    str1.print();
    str2.print();

    //str2.change("learnjava");
    str2 = "learnjava";

    str1.print();
    str2.print();

    return 0;
}

如果您使用的是C ++ 11或更高版本,则可以使用此实现,它遵循五条规则添加移动语义:

#include <iostream>
#include <cstring>
#include <utility>
using namespace std;

class String
{
private:
    char *s;
    int size;
public:
    String(const char *str = nullptr);
    String(const String &src);
    String(String &&src);
    ~String();
    String& operator=(String rhs);
    void print() const;
};

String::String(const char *str)
{
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}

String::String(const String &src)
{
    size = src.size;
    s = new char[size+1];
    strcpy(s, src.s);
}

String::String(String &&src)
{
    size = src.size;
    s = src.s;
    src.s = nullptr;
    src.size = 0;
}

String::~String()
{
    delete [] s;
} 

void String::print() const
{
    cout << s << endl;
}

String& String::operator=(String rhs)
{
    swap(s, rhs.s);
    swap(size, rhs.size);
    return *this;
}

答案 1 :(得分:1)

添加复制构造函数。

String(const String& c){
    size = strlen(c.s);
    s = new char[size+1];
    strcpy(s, c.s);
}