1) 拷贝构造函数和赋值运算符重载的作用:
-
拷贝构造函数:
拷贝构造函数是一种特殊的构造函数,它在以下几种情况下被调用:- 当一个对象通过另一个同类型对象初始化时(如
Class obj2 = obj1;
)。 - 当一个对象作为值传递给函数(按值传递参数时)或从函数返回时。
- 当一个对象作为函数的参数传递时,且是按值传递。
作用:拷贝构造函数的作用是确保在对象复制时,能够正确地复制对象的所有数据,并确保资源(例如堆内存)在拷贝时不会出现重复释放的情况。如果类中有动态分配的资源(如使用
new
分配内存),就需要编写自定义的拷贝构造函数,以确保深拷贝(Deep Copy)而不是浅拷贝(Shallow Copy)。示例
class MyClass { public: int* data; MyClass(int val) { data = new int(val); } // 拷贝构造函数 MyClass(const MyClass& other) { data = new int(*other.data); // 深拷贝 } ~MyClass() { delete data; } };
赋值运算符重载:
赋值运算符重载是在使用=
运算符对一个已存在的对象进行赋值时被调用的。默认的赋值操作是浅拷贝,这对于有动态内存分配的类来说可能会导致问题(如多个对象指向同一块内存)。因此,如果类涉及到动态分配的资源,就需要重载赋值运算符,确保深拷贝,避免资源泄漏或重复释放内存。作用:重载赋值运算符能够保证对象赋值时的正确性,避免浅拷贝所带来的问题,同时防止自我赋值的情况(即对象对自己赋值时),并且正确地释放旧资源。
示例:
- 当一个对象通过另一个同类型对象初始化时(如
-
class MyClass { public: int* data; MyClass(int val) { data = new int(val); } // 赋值运算符重载 MyClass& operator=(const MyClass& other) { if (this != &other) { // 防止自我赋值 delete data; // 释放原来的资源 data = new int(*other.data); // 深拷贝 } return *this; } ~MyClass() { delete data; } };
2) C++模板及其类型:
C++模板是C++提供的一个强大的特性,允许我们编写与类型无关的代码,即可以在编译时根据传入的类型生成不同的代码。模板是为了支持泛型编程,让代码更加通用和灵活。
模板的种类:
-
函数模板(Function Template): 函数模板允许我们编写一个函数来处理不同类型的数据。编译器会根据函数调用时传入的参数类型,自动生成相应类型的函数。
示例:
template <typename T>
T add(T a, T b) {
return a + b;
}
// 使用时,根据传入的参数类型自动推导
int main() {
int result1 = add(3, 5); // int类型
double result2 = add(3.5, 5.5); // double类型
}
模板特化(Template Specialization): 模板特化允许我们为特定类型提供不同的实现。即当模板被某个特定类型实例化时,可以提供一个特定的实现。
示例:
template <typename T>
class MyClass {
public:
void print() { std::cout << "General template" << std::endl; }
};
// 模板特化
template <>
class MyClass<int> {
public:
void print() { std::cout << "Specialized for int" << std::endl; }
};
int main() {
MyClass<double> obj1;
obj1.print(); // 输出 "General template"
MyClass<int> obj2;
obj2.print(); // 输出 "Specialized for int"
}
模板偏特化(Partial Specialization): 偏特化是对模板部分类型进行特化。通过偏特化,我们可以对模板进行更精确的调整。
template <typename T, typename U>
class MyClass {
public:
void print() { std::cout << "General template" << std::endl; }
};
// 偏特化:当T为int时
template <typename U>
class MyClass<int, U> {
public:
void print() { std::cout << "Specialized for int" << std::endl; }
};
int main() {
MyClass<int, double> obj1;
obj1.print(); // 输出 "Specialized for int"
}