`
kmplayer
  • 浏览: 508988 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

条款11:如果class内动态配置有内存,请为此class声明一个copy constructor和一个assignment运算符

阅读更多
1,
定义两个对象:
String a("Hello");
String b("Word");
如下所示:



执行b=a;后,变为:



这样的状况至少存在两个问题:
(1)b原先指向的内存没有被释放掉,内存泄露.
(2)a和b的指针指向相同的字符串,当其中一个离开生存空间,其destructor会删除内存,另外一个悬垂指针.
如:
#include<iostream>
using namespace std;

class String
{
public:
    String(const char* value);
    ~String();
    friend ostream& operator << (ostream& out, const String str);
private:
    char* data;
};

String::String(const char* value)
{
    if (value)
    {
        data = new char[strlen(value)+1];
        strcpy(data, value);
    }
    else
    {
        data = new char[1];
        *data = '\0';
    }
}

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

ostream& operator << (ostream& out, const String str)
{
    return out << str.data;
}


int main()
{
    String a("Hello");
    {
        String b("Word");
        b = a;
    }
    String c=a;
    //这里c.data如今没有定义.
    cout << c << endl;
    return 0;
}

特别注意:String c=a;
这句话调用copy constructor.导致a和c指向同一个地方,这样那个地方会被删除两次.

2,只要程序中有pass-by-value的动作,就会调用copy constructor.
void doNothing(String localString) {}
String s = "The Truth Is Out There";
doNothing(s);
这里s会产生一个副本,函数调用完成后,副本释放,导致s内含指针被删除.
而当s离开作用域,又会对相同的地方再次删除,其行为未定义.

3,解决之道:
(1)如果class拥有任何指针,那么撰写自己的copy constructor和assignment operator.
将指针所指数据结构复制,保证每个对象拥有属于自己的一份拷贝,或者实现某种引用计数策略.
(2)如果你的class不会执行copy或assignment动作,那么将其声明为private,并且不要定义.

4,自己给出的代码:
#include <iostream>
#include <string.h>

using namespace std;

class String
{
public:
    String(const char* value);
    String(const String& rhs);
    ~String();
    String& operator=(const String& rhs);
    friend ostream& operator << (ostream& out, const String str);
private:
    char* data;
};

String::String(const char* value)
{
    if (value)
    {
        data = new char[strlen(value)+1];
        strcpy(data, value);
    }
    else
    {
        data = new char[1];
        *data = '\0';
    }
}

String::String(const String& rhs)
{
    data = new char[strlen(rhs.data)+1];
    strcpy(data, rhs.data);
}

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

String& String::operator=(const String& rhs)
{
    if (this == &rhs)
        return *this;
    delete[] data;
    data = new char[strlen(rhs.data)+1];
    strcpy(data, rhs.data);
    return *this;
}

ostream& operator << (ostream& out, const String str)
{
    return out << str.data;
}


int main()
{
    String a("Hello");
    cout << a << endl;
    {
        String b(a);
        cout << b << endl;
    }
    String c = a;
    cout << c << endl;
    return 0;
}

  • 大小: 28 KB
  • 大小: 34.4 KB
分享到:
评论

相关推荐

    java 赋值运算符、拷贝初始化和this指针_.docx

    - **对象计数问题**:如果每次赋值都创建一个新的对象,那么对象的数量可能会比预期的多很多,这对于维护对象数量有特定需求的场景来说是个问题。 - **返回值**:`return alpha(data);` 返回的是一个对象的副本,...

    快速复制结构体变量和类实例

    在C++中,可以使用拷贝构造函数(Copy Constructor)和赋值运算符(Assignment Operator)来实现深拷贝。拷贝构造函数用于初始化新对象为已有对象的副本,而赋值运算符则用于将一个已存在对象的值赋给另一个对象。这...

    简单类与函数模板实验报告

    实验要求`CStudent`类有一个拷贝构造函数,确保对象复制时正确处理内存分配和姓名的深拷贝。 7. **赋值运算符重载(Overload Assignment Operator)**: - 为了使`Swap`函数模板适用于`CStudent`类,需要重载赋值...

    没有可用的复制构造函数或复制构造函数声明

    理解并正确实现拷贝控制(copy constructor, assignment operator, and destructor)是非常重要的,这就是所谓的"Rule of Three"(在C++11及以后的版本中,通常称为"Rule of Five",因为还包含了move构造函数和move...

    自己编的string类(c++),各种操作基本都有

    然而,有时候为了学习和理解C++类的设计与实现,或者为了满足特定需求,开发者可能会选择自定义一个类似的`string`类。在这个情况下,我们看到了一个用户自己编写的`string`类。下面我们将详细讨论这个自定义`string...

    C++专有名词定义

    89. **赋值运算符(Assignment Operator)**:用于将一个对象的状态复制给另一个对象。 90. **深拷贝(Deep Copy)**:完全复制一个对象及其内部的所有资源。 91. **浅拷贝(Shallow Copy)**:只复制对象本身的引用...

    c++专业英语单词.docx

    9. **Assignment Operator** 和 **Assignment Statement**:赋值运算符和赋值语句,用于将一个值赋给一个变量。 10. **Associativity**:结合性,指运算符在没有括号的情况下如何组合操作数。 11. **Atomic Data ...

    C++箴言:资源管理类的拷贝行为

    // Copy constructor and copy assignment operator are deleted to prevent copying. Lock(const Lock &) = delete; Lock &operator=(const Lock &) = delete; private: Mutex *mutexPtr; }; ``` #### 拷贝...

    (完整版)C++必备专业英语单词(已标注音标).docx

    4. **运算与逻辑单元(Arithmetic Logic Unit, ALU)**:计算机硬件中的一个组成部分,负责执行基本的算术和逻辑运算。 5. **分析(Analysis)**:在软件开发中,分析阶段通常涉及理解问题域并确定解决方案的需求。...

    代码静态分析工具PC-LINT安装配置

    - `error1733: (Info--new in constructor for class 'X' which has no copy constructor)` - 类`X`的构造函数中使用了`new`操作符,但类本身未定义拷贝构造函数。 - `error669: (Warning--Possible data overrun...

    C++常用英语单词.pdf

    14. **赋值运算符(assignment operator)**:如`=`,用于将一个值赋给变量。 15. **综合性(associativity)**:指当有多个运算符同时出现时,它们的结合方式,如左结合或右结合。 16. **备份件(backup copies)**:为...

    工学四川大学C构造函数和析构函数PPT学习教案.pptx

    除了以上介绍,构造函数和析构函数还有其他应用场景,如移动构造函数(Move Constructor)和移动赋值运算符(Move Assignment Operator),这些在现代C++中用于优化对象的复制效率,特别是在处理大对象或资源密集型...

    C++综合实验报告.doc

    3. **拷贝构造函数(Copy Constructor)**:当一个对象被用作另一个对象的初始值时自动调用。在这个实验中,拷贝构造函数用于确保新创建的对象与原有对象具有相同的值。 4. **赋值运算符重载(Overloading ...

    cpp代码-vector容器存放自定义类型

    1. **拷贝构造函数(Copy Constructor)**:拷贝构造函数是一个特殊的构造函数,用于创建一个新对象作为现有对象的副本。对于自定义类型,我们需要提供一个拷贝构造函数,确保当一个对象被复制时,所有成员变量都被...

    ES6练习:学习ES6

    **ES6(ECMAScript 2015)是JavaScript语言的一个重要更新,引入了许多新的特性和语法糖,极大地提升了开发效率和代码可读性。本篇将详细讲解ES6中的核心知识点,帮助你深入理解和掌握这个现代JavaScript的基石。** ...

Global site tag (gtag.js) - Google Analytics