文章目录
0. 缺省 (Default) 概念
缺省,我们联想其英文 defualt
,即默认,可以理解为默认值。
在 C++ 中,“缺省”通常指的是编译器为某些函数、参数、构造函数或其他特性提供的自动化行为或默认值。缺省机制帮助我们简化代码、提高代码的可维护性,并且在许多情况下提高了代码的可读性和可复用性。
缺省机制主要体现在下面几场景:
1. 缺省构造函数
缺省构造函数是当没有提供构造函数时,编译器自动生成的构造函数。它用于初始化类的对象,通常为成员变量提供默认值。如果你没有为类显式定义构造函数,编译器会提供一个默认构造函数。
示例:
class MyClass {
public:
int x;
double y;
};
int main() {
MyClass obj; // 调用缺省构造函数
obj.x = 10;
obj.y = 3.14;
}
对于上面的代码,MyClass
类没有显式定义构造函数,编译器会自动生成一个缺省构造函数。如果显式定义了构造函数,编译器将不会自动生成缺省构造函数,除非进行显式声明。
自定义缺省构造函数:
class MyClass {
public:
int x;
double y;
MyClass() : x(0), y(0.0) {} // 自定义缺省构造函数
};
2. 缺省参数值
在 C++ 中,我们可以为函数参数提供缺省值。即如果调用函数时没有为某个参数传递值,编译器会使用该参数的缺省值。
示例:
#include <iostream>
using namespace std;
void printMessage(const string& message = "abc") {
cout << message << endl;
}
int main() {
printMessage(); // 使用缺省参数值
printMessage("Hello, C++!"); // 使用自定义值
return 0;
}
对于上面的代码,printMessage
函数的参数message
有一个缺省值 "abc"
。当调用printMessage
时,如果没有提供参数,缺省值就会被使用;如果提供了参数,传入的值就会覆盖缺省值。
细节:
- 缺省参数必须从右到左依次提供,即如果一个函数的某个参数提供了缺省值,那么它右边的所有参数也必须提供缺省值。
// 正确
void func(int a, int b = 2, int c = 3);
// 错误
void func(int a = 1, int b, int c = 3);
- 如果函数 的参数全都是缺省,叫做全缺省
- 如果不全是缺省,叫做半缺省
3. 缺省拷贝构造函数和赋值操作符
如果没有显式定义拷贝构造函数或赋值操作符,编译器会提供缺省的拷贝构造函数和赋值操作符。
缺省拷贝构造函数:
class MyClass {
public:
int x;
double y;
};
int main() {
MyClass obj1; // 默认构造
MyClass obj2 = obj1; // 调用缺省拷贝构造函数
}
对于上面的代码,如果我们没有显式定义拷贝构造函数,编译器将自动提供一个成员逐一复制的拷贝构造函数。
自定义拷贝构造函数:
class MyClass {
public:
int x;
double y;
MyClass(const MyClass& other) : x(other.x), y(other.y) {}
};
缺省赋值操作符:
同样,如果你没有定义赋值操作符,编译器会提供一个默认的赋值操作符,它会将右侧对象的每个成员逐一赋值给左侧对象。
class MyClass {
public:
int x;
double y;
};
int main() {
MyClass obj1;
MyClass obj2;
obj2 = obj1; // 调用缺省赋值操作符
}
自定义赋值操作符:
如果类中有指针成员或动态分配的资源,可能需要自定义赋值操作符,避免浅拷贝(浅拷贝会导致资源泄漏)。
class MyClass {
public:
int* x;
MyClass& operator=(const MyClass& other) {
if (this != &other) { // 防止自赋值
*x = *(other.x);
}
return *this;
}
};
4. 缺省模板参数
C++ 允许定义模板时为模板参数提供缺省值,这样在实例化模板时,如果没有提供相应的模板参数,编译器会使用缺省值。
示例:
template <typename T = int>
class MyClass {
public:
T value;
};
int main() {
MyClass<> obj; // 使用缺省模板参数 int
obj.value = 10;
cout << obj.value << endl;
}
对于上面的代码,MyClass
类模板有一个缺省模板参数T
,它的默认类型是int
。当实例化MyClass<>
时,模板参数会自动默认为int
。
5. 缺省类型推断 (auto)
在 C++11 引入的auto
关键字允许编译器根据初始化表达式的类型来推断变量的类型。这简化了代码,并使得代码更加灵活,尤其是对于复杂的类型或迭代器类型。
示例:
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> vec = {1, 2, 3};
// 使用 auto 推断类型
for (auto it = vec.begin(); it != vec.end(); ++it) {
cout << *it << endl;
}
auto x = 42; // 推断出 x 是 int 类型
cout << x << endl;
}
在这个例子中,auto
使得代码更加简洁,避免了手动指定复杂类型。
6. 总结
C++中的“缺省”机制,通过自动化、简化或提供默认行为来提升开发效率。常见的缺省机制包括:
- 缺省构造函数:编译器自动生成构造函数,初始化对象。
- 缺省参数值:函数参数可以指定缺省值,避免在调用时每次都显式传递相同的值。
- 缺省拷贝构造函数和赋值操作符:编译器自动生成拷贝构造函数和赋值操作符,逐成员复制对象。
- 缺省模板参数:模板可以指定缺省类型,使得使用模板时更加灵活。
auto
类型推断:编译器根据初始化表达式推断变量类型,减少代码冗余。