1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 在构造函数中使用new时应注意的事项

在构造函数中使用new时应注意的事项

时间:2019-05-10 03:03:20

相关推荐

在构造函数中使用new时应注意的事项

在构造函数中使用new时应注意的事项

使用new初始化对象的指针成员时必须特别小心。

● 如果在构造函数中使用new来初始化指针成员,则应该在析构函数中使用delete。

● new和delete必须相互兼容。new对应于delete,new[]对应于delete[]。

● 如果有多个析构函数,则必须以相同的方式使用new,要么都带中括号,要么都不带。因为只有一个析构函数,所有的构造函数都必须与它兼容。然而,可以在一个构造函数中使用new初始化指针,而在另一个构造函数中将指针初始化为空,这是因为delete(无论是带中括号还是不带中括号)可以用于空指针。

● 应定义一个复制构造函数,通过深度复制将一个对象初始化为另一个对象。

String::String(const String &st){num_strings++; //如果需要,则处理静态成员更新len = st.len; //复制字符串相同长度str = new char[len + 1]; //分配空间strcpy(str, st.str); //复制字符串给新的地址}

复制构造函数应分配足够的空间来存储复制的数据,并复制数据,而不仅仅是数据的地址,还应该更新所有受影响的静态类成员。

● 应当定义一个赋值运算符,通过深度复制将一个对象复制给另一个对象。

String & String::operator=(const String &st){if (this == &st) //分配对象给它本身return *this;delete[] str; //释放以前的字符串len = st.len; str = new char[len + 1]; //获得空间给新的字符串strcpy(str, st.str); //复制字符串return *this; //返回调用对象的引用}

检查自我赋值的情况,释放成员指针以前指向的内存,复制数据而不仅仅是数据的地址,并返回一个指向调用对象的引用。

应该和不应该

下面的摘要包含了两个不正确的示例,和一个良好的构造函数示例:

String::String(){str = "default string"; //没有new[]len = std::strlen(str);}String::String(const char* s){len = std::strlen(s);str = new char; //没有[]std::strcpy(str, s); //没有申请空间}String::String(const String &st){len = st.len;str = new char[len+1]; //分片空间std::strcpy(str, st.str); //拷贝值}

第一个构造函数没有使用new来初始化str。对默认对象调用析构函数时,析构函数使用delete来释放str。对不是使用new初始化的指针使用delete时,结果将是不确定的,并可能有害的。可将该构造函数修改为下面的任何一种形式:

String::String(){len = 0;str = new char[1]; //利用new和[]str[0] = '\0';}String::String(){len = 0;str = 0; //C++11 str=nullptr}String::String(){static const char* s = "C++"; //初始化仅一次len = std::strlen(s);str = new char[len+1]; //利用new和[]std::strcpy(str, s);}

第二个构造函数使用了new,但分配的内存量不正确。因此,new返回的内存块只能保存一个字符。试图将过长的字符串复制到该内存单元中,将导致内存问题。另外,这里使用的new不带中括号,这与另一个构造函数的正确格式不一致。

第三个构造函数正确。

最后,下面的析构函数无法与前面的构造函数正常地协同工作:

String::~String(){delete str; //应该delete[]str;}

该析构函数未能正确使用delete。由于构造函数创建的是一个字符数组,因此析构函数应该删除一个数组。

包含类成员的类的逐成员复制

假设类成员的类型为String类或标准string类:

class Magazine{private:String title;string publisher;...};

String和string都使用动态内存分配,但这不意味着需要为Magazine类编写复制构造函数和赋值运算符。

默认的逐成员复制和赋值行为有一定的智能。如果将一个Magazine对象复制或赋值给另一个Magazine对象,逐成员复制将使用成员类型定义的复制构造函数和赋值运算符。

复制成员title时,将使用String的复制构造函数,而将成员title赋给另一个Magazine对象时,将使用String的赋值运算符,依次类推。然后,如果Magazine类因其他成员需要定义复制构造函数和赋值运算符,情况将更复杂:这种情况,这些函数必须显式调用String和string的复制构造函数和赋值运算符。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。