在C++中,对象的初始化是一个重要的概念,理解不同类型的初始化方式对于编写高效、可维护的代码至关重要。本文将总结在C++中什么是直接初始化(Direct Initialization)和拷贝初始化(Copy Initialization),并解释在不同情况下分别调用哪种构造函数。
直接初始化(Direct Initialization)
直接初始化是通过构造函数直接初始化对象的方式。在这种方式中,编译器调用匹配的构造函数来创建对象。
语法
直接初始化使用圆括号或大括号进行初始化:
ClassName objectName(arguments); // 圆括号形式
ClassName objectName{arguments}; // 大括号形式(C++11及以后)
示例
class MyClass {
public:
MyClass(int x) {
std::cout << "Constructor with int parameter called." << std::endl;
}
MyClass(const MyClass &other) {
std::cout << "Copy constructor called." << std::endl;
}
};
int main() {
MyClass obj1(10); // 直接初始化,调用带int参数的构造函数
MyClass obj2{20}; // 直接初始化,调用带int参数的构造函数(C++11及以后)
return 0;
}
在上述代码中,obj1
和 obj2
都使用直接初始化方式,调用的是带有整数参数的构造函数。
拷贝初始化(Copy Initialization)
拷贝初始化是通过赋值运算符将一个对象的值赋给另一个对象的方式。这种方式通常调用拷贝构造函数。
语法
拷贝初始化使用等号进行初始化:
ClassName objectName = value;
示例
class MyClass {
public:
MyClass(int x) {
std::cout << "Constructor with int parameter called." << std::endl;
}
MyClass(const MyClass &other) {
std::cout << "Copy constructor called." << std::endl;
}
};
int main() {
MyClass obj1 = 10; // 拷贝初始化,调用带int参数的构造函数然后调用拷贝构造函数
return 0;
}
在上述代码中,obj1
使用拷贝初始化方式。编译器首先使用带整数参数的构造函数创建一个临时对象,然后调用拷贝构造函数将临时对象赋值给obj1
。但实际上,编译器会进行优化,可以跳过拷贝构造函数,直接使用构造函数来构造对象。因此上述代码的输出结果为"Constructor with int parameter called."
。
直接初始化与拷贝初始化的区别
-
调用的构造函数:
- 直接初始化:直接调用匹配的构造函数。
- 拷贝初始化:先调用匹配的构造函数创建临时对象,然后调用拷贝构造函数。
-
性能:
- 直接初始化:效率较高,因为省去了临时对象的创建和拷贝。
- 拷贝初始化:效率较低,因为需要创建临时对象并调用拷贝构造函数。
-
语法风格:
- 直接初始化:适合在构造函数需要多个参数或复杂初始化的情况下使用。
- 拷贝初始化:适合简单的赋值操作,但在性能敏感的场景中应尽量避免。
不同情况下的构造函数调用
使用值初始化
class MyClass {
public:
MyClass() {
std::cout << "Default constructor called." << std::endl;
}
MyClass(int x) {
std::cout << "Constructor with int parameter called." << std::endl;
}
MyClass(const MyClass &other) {
std::cout << "Copy constructor called." << std::endl;
}
};
int main() {
MyClass obj1; // 调用默认构造函数
MyClass obj2(10); // 调用带int参数的构造函数
MyClass obj3 = 20; // 拷贝初始化,调用带int参数的构造函数然后调用拷贝构造函数
MyClass obj4 = obj2; // 调用拷贝构造函数
return 0;
}
使用大括号初始化(C++11及以后)
class MyClass {
public:
MyClass(int x) {
std::cout << "Constructor with int parameter called." << std::endl;
}
MyClass(std::initializer_list<int> list) {
std::cout << "Initializer list constructor called." << std::endl;
}
MyClass(const MyClass &other) {
std::cout << "Copy constructor called." << std::endl;
}
};
int main() {
MyClass obj1{10}; // 调用带int参数的构造函数
MyClass obj2{1, 2, 3}; // 调用初始化列表构造函数
MyClass obj3 = {20}; // 拷贝初始化,调用带int参数的构造函数然后调用拷贝构造函数
return 0;
}
结论
在C++中,直接初始化和拷贝初始化是两种常见的对象初始化方式。直接初始化通过调用构造函数直接初始化对象,而拷贝初始化则通过赋值运算符进行初始化,通常涉及拷贝构造函数。理解它们的区别和适用场景有助于编写高效、清晰的C++代码。