有关深拷贝与重载运算符函数的问题

时间:2023-02-04 17:34:26
class String
{....
String (char *str);        //构造函数
String(String &s);        //带拷贝构造函数
~String();                  //析构函数
....
};
String::String(String &s)                    
{....
  char *src = s.cstr();                      //指向字符串的指针 将字符串的第一个字符传给scr
  content = new char [length+1];    //分配含有length+1个char类型元素的数组  深拷贝
  ....         //并复制内容
}
main()
{...
String str("This is string 1\n"); 
String str2 = "This is string 2\n"; 
...}

主函数中的两句复制一定需要重载运算符函数才能保证避免多次析构指向同一地址的指针吗?
在我看来 这先将字符串隐式转化 然后用指定构造函数创建一个临时对象,按后用复制构造函数将那个临时
对象复制到正在创建的对象,具体说就是调用的是string(char *)构造函数然后调用拷贝构造函数String(String &s)。
问题1:是这里的拷贝构造函数是深拷贝 感觉就不会产生多次析构了啊 我的说法对吗?
问题2:如果对 哪什么情况又必须得用重载运算符函数才保证安全呢?

6 个解决方案

#1


您想重载什么运算符?好含糊啊
String str("This is string 1\n"); //调用构造函数
String str2 = "This is string 2\n";//也直接调用构造函数,没有临时对象产生

#2


主函数的两句都调用了构造函数String (char *str);前者的显式调用,后者是隐式调用。

#3


该回复于2011-05-06 08:59:13被版主删除

#4


main()
{...
  String str1 = "haha";
  String str2 = "xixi";
  String str3 = str1;
  str2 = str1; 
...}
主函数中的两句复制一定需要重载运算符“=”函数才能保证避免多次析构指向同一地址的指针吗?
在我看来 这先将字符串隐式转化 然后用指定构造函数创建一个临时对象,按后用复制构造函数将那个临时
对象复制到正在创建的对象,具体说就是调用的是string(char *)构造函数然后调用拷贝构造函数String(String &s)。
问题1:是这里的拷贝构造函数是深拷贝 感觉就不会产生多次析构了啊 我的说法对吗?
问题2:如果对 哪什么情况又必须得用重载运算符“=”函数才保证安全呢?

#5


“在我看来 这先将字符串隐式转化 然后用指定构造函数创建一个临时对象,按后用复制构造函数将那个临时
对象复制到正在创建的对象,具体说就是调用的是string(char *)构造函数然后调用拷贝构造函数String(String &s)”
您这句话对于String str2 = "This is string 2\n";原本是没错的,但是现在编译器确实不这么做了,去直接构造了。


String str1 = "haha";//构造
String str2 = "xixi";//构造
String str3 = str1;//复制构造
str2 = str1;//operator=



以你最开始给的类得定义来说(我看你代码的意思content是成员变量对吧 )
你无论想深浅拷贝都需要重载复制构造和=
因为默认版的两个函数都仅仅复制content指针(也是一种浅拷贝),结果是两个指针指向一个区域析构是会如同你担心的重复调用delete[];
解决办法是你去重载复制构造和=,这时这两个函数的重载涉及到两种方案
1.浅拷贝(区别默认版得那个浅拷贝,我们这里的目的是把浅拷贝精细化让他虽然指向同一区域但是不会delete多次)
具体实现是加入引用计数,可以google参考智能指针的实现
2.深拷贝
保证对应的复制赋值是深拷贝(你给的代码就是深拷贝时复制构造函数一种实现的例子,但注意申请新空间别忘了释放原来的空间),这样对象析构时不会出现重复delete情况

但是无论那种情况你都要重载两个函数完成不同的目的

#6


谢谢 赤口白舌精彩的解释!

#1


您想重载什么运算符?好含糊啊
String str("This is string 1\n"); //调用构造函数
String str2 = "This is string 2\n";//也直接调用构造函数,没有临时对象产生

#2


主函数的两句都调用了构造函数String (char *str);前者的显式调用,后者是隐式调用。

#3


该回复于2011-05-06 08:59:13被版主删除

#4


main()
{...
  String str1 = "haha";
  String str2 = "xixi";
  String str3 = str1;
  str2 = str1; 
...}
主函数中的两句复制一定需要重载运算符“=”函数才能保证避免多次析构指向同一地址的指针吗?
在我看来 这先将字符串隐式转化 然后用指定构造函数创建一个临时对象,按后用复制构造函数将那个临时
对象复制到正在创建的对象,具体说就是调用的是string(char *)构造函数然后调用拷贝构造函数String(String &s)。
问题1:是这里的拷贝构造函数是深拷贝 感觉就不会产生多次析构了啊 我的说法对吗?
问题2:如果对 哪什么情况又必须得用重载运算符“=”函数才保证安全呢?

#5


“在我看来 这先将字符串隐式转化 然后用指定构造函数创建一个临时对象,按后用复制构造函数将那个临时
对象复制到正在创建的对象,具体说就是调用的是string(char *)构造函数然后调用拷贝构造函数String(String &s)”
您这句话对于String str2 = "This is string 2\n";原本是没错的,但是现在编译器确实不这么做了,去直接构造了。


String str1 = "haha";//构造
String str2 = "xixi";//构造
String str3 = str1;//复制构造
str2 = str1;//operator=



以你最开始给的类得定义来说(我看你代码的意思content是成员变量对吧 )
你无论想深浅拷贝都需要重载复制构造和=
因为默认版的两个函数都仅仅复制content指针(也是一种浅拷贝),结果是两个指针指向一个区域析构是会如同你担心的重复调用delete[];
解决办法是你去重载复制构造和=,这时这两个函数的重载涉及到两种方案
1.浅拷贝(区别默认版得那个浅拷贝,我们这里的目的是把浅拷贝精细化让他虽然指向同一区域但是不会delete多次)
具体实现是加入引用计数,可以google参考智能指针的实现
2.深拷贝
保证对应的复制赋值是深拷贝(你给的代码就是深拷贝时复制构造函数一种实现的例子,但注意申请新空间别忘了释放原来的空间),这样对象析构时不会出现重复delete情况

但是无论那种情况你都要重载两个函数完成不同的目的

#6


谢谢 赤口白舌精彩的解释!