C++ 动态内存和类

25 阅读3分钟
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运算符
  1. 什么是定位 new?
普通 new vs 定位 new
// 普通 new:分配内存 + 构造对象
MyClass* p1 = new MyClass();

// 定位 new:在指定内存上构造对象(不分配内存!)
void* buffer = operator new(sizeof(MyClass));  // 只分配内存
MyClass* p2 = new (buffer) MyClass();          // 在 buffer 上构造

核心区别

  • 普通 new分配内存 + 调用构造函数
  • 定位 new只调用构造函数,内存由你提供
  1. 定位 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重载<<运算符
  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 返回值 类名::函数名(参数);精确控制访问权限