[NOTE] Updated December 5, 2023. This article may have outdated content or subject matter.
在 C++ 里,关注一个对象的“生命周期”,意味着了解如何创建对象、拷贝(COPY)对象、移动(MOVE)对象以及如何销毁对象,首先来定义什么是 COPY 和 MOVE:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
string ident(string arg) // string passed by value (copied into arg)
{
return arg; // return str ing (move the value of arg out of ident() to a caller)
}
int main ()
{
string s1 {"Adams"}; // initialize str ing (constr uct in s1).
s1 = indet(s1); // copy s1 into ident()
// move the result of ident(s1) into s1;
// s1’s value is "Adams".
string s2 {"Pratchett"}; // initialize str ing (constr uct in s2)
s1 = s2; // copy the value of s2 into s1
// both s1 and s2 have the value "Pratchett".
}
|
这个例子用到了多个函数:
- s1和s2用字符串常量初始化string的构造函数
- 传值的函数入参做了 copy
- 返回时将结果 move 到一个临时变量
- move 临时变量到 s1
- s2 拷贝赋值到 s1
- 析构函数释放所有资源
总结一个通用的类 X 需要下面这些构造函数:
1
2
3
4
5
6
7
8
9
10
|
class X {
X(Sometype); // ordinary constructor: create an object
X(); // default constructor
X(const X &); // copy constructor
X(X &&); // move constructor
X &operator=(const X &); // copy assignment: clean up target and copy
X &operator=(X &&); // move assignment: clean up target and move
˜X(); // destructor: clean up
// ...
};
|
构造函数和析构函数
- 构造函数中常常要保证一些 invariant(不变式),类似于 size 必须严格和类中的数量相等。
- 构造函数可以很好的与继承关系配合,自顶向下的创建对象,沿着
基类->成员->自身
的顺序进行构造。析构则反之。
- 在内存区域显式管理内存时可能会手动调用构造/析构函数,例如 vector 的 push_back 和 pop_back,会进行放置式 new。
- 基类的析构函数应当被声明为 virtual。
类对象初始化
- Init Without Constructors
- 基础类型直接初始化
- 无构造函数类可以用 逐成员、copy、default init
- 要注意默认类型只声明的时候是不初始化的
- Init Using Constructors
- 显示定义了一个构造函数后,默认构造函数就消失了,但是拷贝构造函数依然有默认实现
- 推荐用 {} 初始化,而不是 ()、=,{} 不允许窄化转换
- constructor 可以用 std::initializer_list 作为参数做初始化,要保证相互之间是同构的(homogeneous)
Author
lawrshen
LastMod
2023-12-05
(eadabb8)
License
CC BY-NC-ND 4.0