const T& val = T()
以下是vector类模拟实现中 resize() 部分代码:
cpp
/* resize */
// val不能给0,因为不知道T的类型,所以给一个T的缺省值
void resize(size_t n, const T& val = T())
{
// 缩小size
if (n < size())
_finish = _start + n;
else // 增大size
{
// 假如需要扩容
if (n > capacity())
{
reserve(n);
}
while (_finish < _start + n)
{
*_finish = val;
++_finish;
}
}
}
const T& val = T()
的含义
这行代码实际上包含了三个关键概念:
1. T()
- 值初始化
-
T()
表示创建一个类型为T
的临时对象,并使用值初始化 -
对于内置类型(如
int
,double
,指针
等),T()
会将其初始化为零值:-
int()
→0
-
double()
→0.0
-
char()
→'\0'
-
指针()
→nullptr
-
-
对于类类型,
T()
会调用默认构造函数
2. const T&
- 常量引用
-
使用常量引用可以避免不必要的对象拷贝
-
常量引用可以绑定到临时对象(如
T()
创建的对象)
3. = T()
- 默认参数
- 这是函数的默认参数,如果调用时不提供这个参数,就使用
T()
作为默认值
为什么要这样设计?
通用性
由于 vector
是模板类,需要处理任意类型 T
:
-
如果是
vector<int>
,T()
就是0
-
如果是
vector<string>
,T()
就是空字符串 -
如果是
vector<MyClass>
,T()
会调用MyClass
的默认构造函数
示例代码:
cpp
vector<int> v1;
v1.resize(10); // 使用默认值 int() = 0,所有新元素初始化为0
vector<double> v2;
v2.resize(5); // 使用默认值 double() = 0.0
vector<string> v3;
v3.resize(3); // 使用默认值 string() = 空字符串// 也可以显式指定值
v1.resize(15, 100); // 新元素初始化为100
v3.resize(5, "hello");// 新元素初始化为"hello"
为什么不能直接用 0
?
为什么不能写成 void resize(size_t n, const T& val = 0)
?
这是因为:
-
类型不匹配:如果
T
是string
,0
不是有效的字符串值 -
缺乏通用性:不是所有类型都能从
0
构造 -
编译错误:对于不能从
0
转换的类型,代码无法编译
而 T()
为每种类型提供了最合适的"零值"或默认值,保证了代码的通用性和类型安全。
总结
const T& val = T()
是一个巧妙的设计:
-
通用:适用于任何类型
T
-
高效:使用引用避免拷贝
-
安全:提供类型安全的默认值
-
灵活:允许调用者提供自定义值,也有合理的默认值
这种写法在STL和现代C++库中非常常见,是编写通用模板代码的重要技巧之一。