C++深入解析:new操作符的秘密

需积分: 12 1 下载量 141 浏览量 更新于2024-09-17 1 收藏 35KB DOC 举报
"深入C++基础_new运算符.doc" 在C++编程语言中,`new`关键字扮演着至关重要的角色,特别是在动态内存管理方面。`new`不仅是一个关键字,同时也是一个操作符,它允许我们在程序运行时在堆上分配内存,用于创建对象或数组。由于其复杂性和灵活性,`new`在C++中的应用广泛,但也带来了相应的挑战。 ### new的过程 当使用`new`创建对象时,通常会执行以下三个步骤: 1. **内存分配**:`new`首先尝试在堆上获取足够大小的内存块。如果内存不足,系统可能会尝试进行垃圾回收或者调用内存分配失败处理程序(`new_handler`)来尝试释放内存并再次尝试分配。 2. **构造函数调用**:如果内存分配成功,`new`会调用对应的构造函数初始化新分配的对象。对于基本类型的变量,这一步会被忽略,因为它们不需要构造。 3. **返回指针**:最后,`new`返回一个指向新分配内存的指针,供后续代码使用。 举个例子,如果我们有如下的类`A`: ```cpp class A { int i; public: A(int _i):i(_i*_i) {} void Say() { printf("i=%d\n", i); } }; ``` 使用`new`创建`A`对象的代码: ```cpp A* pa = new A(3); ``` 这等价于执行以下三个步骤,但内存分配失败处理和异常处理等细节未被体现: ```cpp void* memory = operator_new(sizeof(A)); // 内存分配 new (memory) A(3); // 调用构造函数 A* pa = static_cast<A*>(memory); // 指针转换 ``` ### new的三种形态 C++中的`new`可以有三种不同的含义: 1. **new operator**:也就是我们通常使用的`new`表达式,它包含了上述的内存分配、对象构造和指针返回。 2. **operator new**:这是一个可以被重载的操作符,负责实际的内存分配。默认情况下,如果内存分配失败,`new`会调用`new_handler`。通过重载`operator new`,我们可以自定义内存分配策略,比如增加日志记录、定制错误处理等。 3. **placement new**:这是一种特殊的`new`形式,它不进行内存分配,而是用于在已知地址处构造对象。这在内存池、对象复用等场景下很有用。 ### 自定义`operator new` 下面是一个重载`operator new`的例子: ```cpp class A { public: void* operator new(size_t size) { printf("operator new called\n"); void* ptr = ::operator new(size); // 调用全局的operator new if (!ptr) throw std::bad_alloc(); // 处理分配失败 return ptr; } }; ``` 在这个例子中,当我们为`A`类对象调用`new`时,会先打印一条消息,然后调用全局的`operator new`,如果分配失败则抛出异常。 总结起来,深入理解`new`在C++中的作用和工作原理对于编写高效、健壮的代码至关重要。熟练掌握`new`的不同形态和如何自定义`operator new`可以帮助开发者更好地控制内存管理,避免内存泄漏和其他相关问题。