More Effective C++:理解new和delete
2013-08-16 15:40
447 查看
http://dev.yesky.com/242/2585242.shtml
人们有时好像喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和operator new的区别。
当你写这样的代码:
string *ps = new string("Memory Management"); |
你所能改变的是如何为对象分配内存。new操作符调用一个函数来完成必需的内存分配,你能够重写或重载这个函数来改变它的行为。new操作符为分配内存所调用函数的名字是operator new。
函数operator new 通常这样声明:
void * operator new(size_t size); |
你一般不会直接调用operator new,但是一旦这么做,你可以象调用其它函数一样调用它:
void *rawMemory = operator new(sizeof(string)); |
就象malloc一样,operator new的职责只是分配内存。它对构造函数一无所知。operator new所了解的是内存分配。把operator new 返回的未经处理的指针传递给一个对象是new操作符的工作。当你的编译器遇见这样的语句:
string *ps = new string("Memory Management"); |
void *memory = // 得到未经处理的内存 operator new(sizeof(string)); // 为String对象 call string::string("Memory Management") //初始化 on *memory; // 内存中 // 的对象 string *ps = // 是ps指针指向 static_cast<string*>(memory); // 新的对象 |
Placement new
有时你确实想直接调用构造函数。在一个已存在的对象上调用构造函数是没有意义的,因为构造函数用来初始化对象,而一个对象仅仅能在给它初值时被初始化一次。但是有时你有一些已经被分配但是尚未处理的的(raw)内存,你需要在这些内存中构造一个对象。你可以使用一个特殊的operator new ,它被称为placement new。
下面的例子是placement new如何使用,考虑一下:
class Widget { public: Widget(int widgetSize); ... }; Widget * constructWidgetInBuffer(void *buffer,int widgetSize) { return new (buffer) Widget(widgetSize); } |
在constructWidgetInBuffer里面,返回的表达式是:
new (buffer) Widget(widgetSize) |
void * operator new(size_t, void *location) { return location; } |
new,你必须使用语句#include <new>(或者如果你的编译器还不支持这新风格的头文件名(再参见Effective C++ 条款49),<new.h>)。
让我们从placement new回来片刻,看看new操作符(new operator)与operator new的关系,你想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。如果你仅仅想分配内存,就应该调用operator new函数;它不会调用构造函数。如果你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数,然后使用new操作符,new操作符会调用你定制的operator new。如果你想在一块已经获得指针的内存里建立一个对象,应该用placement
new。
(有关更多的不同的new与delete的观点参见Effective C++ 条款7和我的文章Counting objects。)
Deletion and Memory Deallocation
为了避免内存泄漏,每个动态内存分配必须与一个等同相反的deallocation对应。函数operator delete与delete操作符的关系与operator new与new操作符的关系一样。当你看到这些代码:
string *ps; ... delete ps; // 使用delete 操作符 |
Operator delete用来释放内存,它被这样声明:
void operator delete(void *memoryToBeDeallocated); |
导致编译器生成类似于这样的代码:
ps->~string(); // call the object's dtor operator delete(ps); // deallocate the memory // the object occupied |
void *buffer = // 分配足够的 operator new(50*sizeof(char)); // 内存以容纳50个char //没有调用构造函数 ... operator delete(buffer); // 释放内存 // 没有调用析构函数 |
如果你用placement new在内存中建立对象,你应该避免在该内存中用delete操作符。因为delete操作符调用operator delete来释放内存,但是包含对象的内存最初不是被operator new分配的,placement new只是返回转递给它的指针。谁知道这个指针来自何方?而你应该显式调用对象的析构函数来解除构造函数的影响:
// 在共享内存中分配和释放内存的函数 void * mallocShared(size_t size);
void freeShared(void *memory);
void *sharedMemory = mallocShared(sizeof(Widget));
Widget *pw = // 如上所示,
constructWidgetInBuffer(sharedMemory, 10); // 使用
// placement new
...
delete pw; // 结果不确定! 共享内存来自
相关文章推荐
- More Effective C++之Item M8:理解各种不同含义的new和delete
- More Effective C++----(8)理解各种不同含义的new和delete
- More Effective C++ ——08_理解各种不同含义的new和delete
- More Effective C++:理解new和delete
- more-effective-c++ 序列1 new和delete的测试
- 《More Effective C++》学习心得(六)各种new和delete操作符
- More Effective C++:不同new和delete
- 《More Effective C++》Rule8:了解各种不同意义的new和delete(上)
- More Effective C++:不同new和delete
- More Effective C++ 条款8 了解各种不同意义的new和delete
- More Effective C++(条款8:了解各种不同意义的new和delete)
- more effective c++第二章读书笔记:c++的运算符,运算符转换,前缀自增和后缀自增,operatpr new和operator delete.
- Effective C++ 3nd 读书摘要(八、定制new和delete)Item49 - 52
- effective C++ 学习 (Customizing new and delete)
- 读书笔记 effective c++ Item 16 成对使用new和delete时要用相同的形式
- <<Effective C++>>读书笔记8: 定制new和delete
- C++中operator new 和 new operator小结以及对new 和 delete初步理解
- 读书笔记_Effective_C++_条款十六:成对使用new和delete时要采取相同的形式
- 读书笔记 effective c++ Item 16 成对使用new和delete时要用相同的形式
- Effective C++ 52. Write placement delete if you write placement new