C++复制构造函数
即使有多年经验的C++程序员也容易犯复制构造函数(复制对象)的错误,并且会说:“我没有复制过这个对象嘛。”
其实不知不觉中,有时程序中已经有了复制构造函数,一下情况,会有复制对象的发生,总结:
1) 根据领一个同类型的对象显示或隐式初始化一个对象;
2) 函数中对象作为实参传入:复制一个对象,将它作为实参传给一个函数;
3) 从函数返回时复制一个对象;
4) 初始化顺序容器中的元素;
5) 根据元素初始化式列表初始化数组元素;
当以上5条中有一条发生,而被复制的对象中有指针,就带来严重bug的风险。
规避此风险的方法:
1) 注意自定义此对象的复制构造函数,让编译器默认的合成复制构造函数不起作用;
2) 函数参数的传入用指针或引用,不要使用对象;
3) 函数返回值采用指针和引用,不要使用对象;
合成复制构造函数
若是我们没有定义复制构造函数,编译器自动会帮我们弄出一个合成复制构造函数,完成对象每个非static成员的初始化(以源对象为copy源)。
一般得成员:内置类型,数组,迭代器都能用编译器默认的合成复制构造函数,但是对象内部有指针成员,就会出问题。
自定义复制构造函数
Class Foo
{
public:
Foo();
Foo(const Foo& inParam)/*const 引用类型*/
{
....
}
}
合成类对象复制操作符=
若是类没有定义复制操作符=,编译器会帮我们弄出一个合成复制操作符=,完成对象每个非static成员的赋值操作。
Foo fo1;
Foo fo2;
fo1.setValue(100);
fo2.SetValue(200);
fo2 = fo1;/*注意:被复制对象内部的成员会被右值中的对象成员覆盖*/
自定义类对象复制操作符=
Class Foo
{
public:
Foo();
Foo(const Foo& inParam)/*const 引用类型*/
{
....;
}
Foo& operate=(const Foo& inParam)
{
if(this == &inParam)/*注意:被复制对象内部的成员会被右值中的对象成员覆盖, 防止被自己被自己覆盖*/
{
return;
}
}
}
自定义复制构造函数和自定义复制操作符=常一起使用:
注意:需要形成编程规范,以下两者都必须定义
1)自定义复制构造函数;
2)自定义类对象复制操作符;
禁止复制:
若是类对象的成员中有指针,且不需要复制操作,一定要禁止复制(运用以下手段)
禁止复制的手段:设置复制构造函数和类对象操作符为private, 并且只声明不定义;
解释:
都设置为private: 为了防止被使用;
只声明不定义:防止友元的访问;
显式析构函数、自定义复制构造函数和自定义复制操作符=的tips:
1)若显式析构函数存在,自定义复制构造函数和自定义复制操作符=必须存在;
2)若自定义复制构造函数和自定义复制操作符=存在,显式析构函数必须存在;
原因很简单,都需要对必要的资源进行操作,以上两条必须生成编程规范!!!