12.1.2 特殊成员函数
1.默认构造函数
如果定义了构造函数,C++将不会定义默认构造函数
2.复制构造函数
3.何时调用复制
当按值传递和返回对象时,都将调用复制构造函数
4.默认的复制构造函数的功能
默认的复制构造函数逐个复制非静态成员(成员复制也称为浅复制(就是浅拷贝)),复制的是成员的值
12.4 有关返回对象的说明
1.返回指向const对象的引用
使用const引用的常见原因是旨在提高效率,但对于何时采用这种方式存在一些限制。如果函数返回的是传递给它的对象,可以通过返回引用提高其效率。 示例:
// version1
Vector Max(const Vector & v1, const Vector & v2)
{
if(v1.magval() > v2.magval())
return v1;
else
return v2;
}
// verson2
const Vector & Max()(const Vector & v1, const Vector & v2)
{
if(v1.magval() > v2.magval())
return v1;
else
return v2;
}
返回对象将调用复制构造函数,而返回引用不会。因此,第二个版本所做的工作更少,效率更高。
2.返回指向非const对象的引用
3.返回对象
如果被返回的对象是被调用函数中的局部变量,则不应该按应用的方式返回它,因为在被调用函数执行完毕时,局部对象将调用其析构函数。
4.返回const对象
12.5使用指向对象的指针
12.5.1再谈new和delete
内存布局图示:
内存区域示意图:
+------------------+ 高地址
| 栈 |
| stack_obj | ← 局部变量
| ptr (指针本身) |
+------------------+
| 堆 |
| *heap_obj | ← new 创建的对象
+------------------+
| 数据段 |
| global_obj | ← 全局变量
| static_local | ← 静态局部变量
+------------------+
| 代码段 |
| 函数指令 |
+------------------+ 低地址
关于析构函数:
- 栈对象:离开作用域时自动调用析构函数
- 堆对象(new创建):只有
delete时才调用析构函数 - 全局/静态对象:程序结束时自动调用析构函数
12.5.2 指针和对象小结
12.5.3 再谈定位new运算符
- 什么是定位 new?
普通 new vs 定位 new
// 普通 new:分配内存 + 构造对象
MyClass* p1 = new MyClass();
// 定位 new:在指定内存上构造对象(不分配内存!)
void* buffer = operator new(sizeof(MyClass)); // 只分配内存
MyClass* p2 = new (buffer) MyClass(); // 在 buffer 上构造
核心区别:
- 普通
new:分配内存 + 调用构造函数 - 定位
new:只调用构造函数,内存由你提供
- 定位 new 的语法
// 基本语法
new (place_address) type(initializer_list)
// 示例
#include <new> // 需要包含这个头文件
// 1. 在栈上构造
char buffer[sizeof(MyClass)];
MyClass* obj1 = new (buffer) MyClass();
// 2. 在堆上构造
void* mem = operator new(sizeof(MyClass));
MyClass* obj2 = new (mem) MyClass(42, "hello");
// 3. 在指定地址构造
MyClass* obj3 = new ((void*)0x1000) MyClass(); // 在地址 0x1000 处构造
12.6复习各种技术
12.6.1重载<<运算符
- 友元
友元是 C++ 中一个特殊的机制,它允许非成员函数或其他类访问当前类的私有(private)和保护(protected)成员。
基本语法
class MyClass {
private:
int secret;
public:
MyClass(int s) : secret(s) {}
// 声明友元函数
friend void showSecret(const MyClass& obj);
};
// 友元函数的定义(普通函数)
void showSecret(const MyClass& obj) {
// 可以直接访问私有成员 secret
cout << "Secret value: " << obj.secret << endl;
}
int main() {
MyClass obj(42);
showSecret(obj); // 输出:Secret value: 42
return 0;
}
总结
| 友元类型 | 语法 | 典型用途 |
|---|---|---|
| 友元函数 | friend 返回值 函数名(参数); | 运算符重载(<<、>>) |
| 友元类 | friend class 类名; | 紧密协作的类(容器-迭代器) |
| 友元成员函数 | friend 返回值 类名::函数名(参数); | 精确控制访问权限 |