【问题标题】:c++ deep copy constructor [duplicate]c ++深拷贝构造函数[重复]
【发布时间】:2018-04-28 05:32:16
【问题描述】:

这是我的代码:

#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中,它不能。

【问题讨论】:

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


    【解决方案1】:

    您的课程没有遵循 Rule of Three,因为它缺少正确的复制构造函数。

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

    由于您没有提供复制构造函数,因此编译器为您提供了一个,但它不会对 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;
    }
    

    【讨论】:

    • 是的,你是对的,我没有按照规则,但是删除用户定义的复制构造函数后,错误才出现,你是这样的吗?
    • @Jean 你的意思是你明确地delete 复制构造函数(String(const String&amp;) = delete)?你到底得到了什么错误?如果你 delete 复制构造函数,那么像 String str2 = str1;(和 String str2(str1);)这样的语句就不能再编译了。另外,可能相关:Default move constructor/assignment and deleted copy constructor/assignment
    • 正如文章所说,存在“*** Error in `./code': double free or corruption (fasttop): 0x0000000000f7f010 ***”。好吧,我可以在 ubuntu 14.04 中编译它
    【解决方案2】:

    添加一个复制构造函数。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-11
      • 1970-01-01
      • 2013-03-09
      相关资源
      最近更新 更多