C++: 拷贝管理
2015-11-08 04:03
337 查看
《C++ Primer》看到这一章我都惊呆了,C++竟然还能有这种功能:类可以控制该类型对象拷贝、赋值、移动和销毁时做什么。
以上操作通过:拷贝构造函数、移动构造函数、拷贝赋值运算符、移动赋值运算符、以及析构函数构成。
本质上是个构造函数,所以它出现就会构造新对象,没有新对象它就没出现。
拷贝构造函数的第一个参数必须是一个引用类型,因为如果是值传递方式穿参的话,会立即再次调用拷贝构造函数,这样就形成无限递归了!危险!
如果我们没有自定义一个拷贝构造函数,编译器会自动帮我们合成一个。默认拷贝构造函数会将其参数成员逐个拷贝到正在创建的对象中。
以下情况会发生拷贝初始化:
1. 用=定义变量。
2. 将一个对象作为实参传递给一个非引用类型的形参。
3. 从一个返回类型为非引用类型的函数返回一个对象。
4. 列表初始化一个数组中的元素或一个聚合类中的成员。
有个小坑是,
当然要成为一个伟大的赋值运算符,当然要付出一点代价:
1. 名字必须是
2. 必须定义为成员函数
3. 左侧运算对象就绑定到隐式的this参数上
4. 接受一个与其所在类相同类型的参数
5. 为了与内置类型的赋值保持一致,返回指向左侧对象的引用。
如果类没有定义自己的拷贝赋值操作符,编译器会自动生成一个。它会将右侧运算对象的每个非static成员赋予左侧运算对象的对应成员。
跟构造函数一样的是:没有返回类型,如果没自定义,编译器就会生成一个默认的。
跟构造函数不一样的是:没有构造函数初始化列表,名字是类名前加一个波浪号~,析构函数不接受参数,所以不能被重载,不能定义为delete。
note:析构函数先执行函数体,然后销毁成员,顺序按初始化的逆序。销毁一个内置类型的指针不会delete它指向的对象。
以上操作通过:拷贝构造函数、移动构造函数、拷贝赋值运算符、移动赋值运算符、以及析构函数构成。
拷贝构造函数:
定义: 如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。本质上是个构造函数,所以它出现就会构造新对象,没有新对象它就没出现。
拷贝构造函数的第一个参数必须是一个引用类型,因为如果是值传递方式穿参的话,会立即再次调用拷贝构造函数,这样就形成无限递归了!危险!
如果我们没有自定义一个拷贝构造函数,编译器会自动帮我们合成一个。默认拷贝构造函数会将其参数成员逐个拷贝到正在创建的对象中。
以下情况会发生拷贝初始化:
1. 用=定义变量。
2. 将一个对象作为实参传递给一个非引用类型的形参。
3. 从一个返回类型为非引用类型的函数返回一个对象。
4. 列表初始化一个数组中的元素或一个聚合类中的成员。
有个小坑是,
A aa = a;像这样定义并初始化一个A类型的变量aa,只会调用拷贝构造函数,不会调用拷贝赋值运算符。
#include <iostream> using namespace std; class A{ public: A(int i=0):n(i){} A(A &a, int i=0):n(i){ cout<< a.getI() <<endl; cout<< getI() <<endl; cout<<"hello"<<endl; } const int getI(){ return n; } private: int n = 0; }; int main(){ A a(998); A b = a;//调用拷贝构造函数 //输出结果为: //998 //0 //hello //证明 a 被当成了拷贝构造函数的第一个参数 return 0; }
拷贝赋值运算符
这其实就是个操作符重载。本质上是个名为operator=的函数,所有有形参有返回值,有函数体,都有。
当然要成为一个伟大的赋值运算符,当然要付出一点代价:
1. 名字必须是
operator=
2. 必须定义为成员函数
3. 左侧运算对象就绑定到隐式的this参数上
4. 接受一个与其所在类相同类型的参数
5. 为了与内置类型的赋值保持一致,返回指向左侧对象的引用。
如果类没有定义自己的拷贝赋值操作符,编译器会自动生成一个。它会将右侧运算对象的每个非static成员赋予左侧运算对象的对应成员。
#include <iostream> using namespace std; class A{ public: A(int i=0):n(i){} A(A &a, int i=0):n(i){ cout<< a.getI() <<endl; cout<< getI() <<endl; cout<<"hello"<<endl; } A &operator=(const A &r){ n = r.n; cout<<"copying..."<<endl; return *this; } const int getI(){ return n; } private: int n = 0; }; int main(){ A a(998); A b(333); b = a; cout<< b.getI()<<endl; //copying... //998 return 0; }
析构函数:
析构函数释放对象使用的资源,并销毁对象的非static数据成员。跟构造函数一样的是:没有返回类型,如果没自定义,编译器就会生成一个默认的。
跟构造函数不一样的是:没有构造函数初始化列表,名字是类名前加一个波浪号~,析构函数不接受参数,所以不能被重载,不能定义为delete。
note:析构函数先执行函数体,然后销毁成员,顺序按初始化的逆序。销毁一个内置类型的指针不会delete它指向的对象。
相关文章推荐
- [并发并行]_[C/C++]_[使用线程本地存储Thread Local Storage(TLS)调用复制文件接口的案例]
- [并发并行]_[C/C++]_[使用线程本地存储Thread Local Storage(TLS)调用复制文件接口的案例]
- c++ 11 数组 和lambda表达式 语法 / 函数包装器 基本用法
- 编译原理(一) Chomsky文法的判断方法及C++代码实现
- Effective C++ 笔记 第三部分 资源管理
- c++在类的内部访问全局变量
- To be a better man!
- 用C语言写的ATM程序
- C++实现单链表
- c语言之const理解
- C/C++基础面试题
- c++调用ado执行带参数的sql(非存储过程)
- C++ sstream 中处理字符串
- const char*, char const*, char*const的区别
- C++中push_back的注意事项
- 记录C语言入门·三
- c++rand()与srand()的使用
- C语言版Trim()函数,去除字符串中的空字符
- C语言版GetPrivateProfileString()函数,从初始化文件中指定的条目取得字串
- C++声明和定义的区别 收藏