看不懂..............
<code class="lang-cpp">#include <iostream> using namespace std; struct MyClass { MyClass() { cout << "构造函数" << endl; } virtual ~MyClass() { cout << "析构函数" << endl; } }; int main() { char k[sizeof(MyClass)]; // 预先分配内存k[] MyClass* ptr1 = new(k) MyClass; // 在k[]中生成新对象 new(void*) MyClass(); ptr1->~MyClass(); // 直接调用析构函数,销毁对象 char m[sizeof(int) + 2*sizeof(MyClass)]; // 预先分配内存m[](计数空间+数据空间) MyClass* ptr2 = new(m) MyClass[2]; // 在m[]中生成新MyClass对象 ptr2[1].~MyClass(); // 直接调用析构函数,销毁对象 ptr2[0].~MyClass(); // 直接调用析构函数,销毁对象 return 0; }</iostream></code>上边出现了显式调用析构函数的语句,C++中析构函数是可以直接调用的。而构造函数却不能直接调用(直接调用的含义是新建临时值对象),需要使用new(void*)这种特殊方法。
<code class="lang-cpp">// 单变量形式 ptr1 = new MyClass(...); ptr2 = new(nothrow) MyClass(...); ptr3 = new(&buffer) MyClass(...); // 此处需要 sizeof(MyClass) 字节空间 delete ptr1; // 示例:析构并释放ptr1指向的对象 // 数组形式 ptr1 = new MyClass[3](...); ptr2 = new(nothrow) MyClass[3](...); ptr3 = new(&buffer) MyClass[3](...); // 此处需要 sizeof(int) + 3 * sizeof(MyClass) 字节空间 delete[] ptr1; // 示例:析构并释放ptr1指向的对象数组</code>new和delete运算符的重载(operator new、operator delete)并不需要调用构造函数或析构函数,operator new只需分配内存,并返回内存块的起始地址,而operator delete只需释放内存。
<code class="lang-cpp">// 单变量形式 void* operator new(size_t sz); // 常规new(可抛出bad_alloc异常) void* operator new(size_t sz, nothrow_t nt); // 无抛出new(可返回NULL) void* operator new(size_t sz, void *place); // 就地new(直接返回place,不分配内存) void operator delete(void *obj); // 显式delete & “常规new”的隐式delete void operator delete(void *obj, nothrow_t nt); // “无抛出new”的隐式delete void operator delete(void *obj, void *place); // “就地new”的隐式delete // 数组形式 void* operator new[](size_t sz); // 常规new[](可抛出bad_alloc异常) void* operator new[](size_t sz, nothrow_t nt); // 无抛出new[](可返回NULL) void* operator new[](size_t sz, void *place); // 就地new[](直接返回place,不分配内存) void operator delete[](void *obj); // 显式delete[] & “常规new[]”的隐式delete[] void operator delete[](void *obj, nothrow_t nt); // “无抛出new[]”的隐式delete[] void operator delete[](void *obj, void *place); // “就地new[]”的隐式delete[]</code>比如以下代码可以让C++调用对应的隐式delete——
<code class="lang-cpp">#include <iostream> using namespace std; struct MyClass{ MyClass() { // 构造函数 cout << "抛出异常的构造函数" << endl; throw exception(""); // 抛出异常 } }; int main() { try { MyClass *ptr = new(nothrow) MyClass; // 分配成功,但构造函数抛出异常 delete ptr; // 这句不会被执行 } catch (exception& e) { // 自动执行void operator delete(void *, nothrow_t) } return 0; }</iostream></code>如果在类中重载了一对new和delete,那么在new或delete这个类的对象时,C++只会在类中搜索new或delete,不会在全局搜索。所以,对于重载new或delete运算符的C++类,需要同时重载三种形式。
<code class="lang-cpp">struct MyClass { void* operator new(size_t sz) { cout << "operator new" << endl; return ::operator new(sz); // 调用全局new } void operator delete(void * ptr) { cout << "operator delete" << endl; return ::operator delete(ptr); // 调用全局delete } };</code>实际上operator new和operator new[]的参数数量并没有限制,形式可以为void* operator new(size_t, ...),只需要保证第一个参数size_t和返回值void*的类型正确即可。这些重载形式均可以用new(...)形式调用。但是也要注意,如果写了某一个new重载,那么还需要再写一个相对应形式的void operator delete(void*, ...)以处理构造函数抛出异常的情况,同样需要注意第一个参数void*和返回值void的类型正确。
<code class="lang-cpp">struct MyClass { void* operator new(size_t sz, string msg, int val) // 自定义new运算符 { cout << "new: " << msg.c_str() << " " << val << endl; return ::operator new(sz); } void operator delete(void *ptr, string msg, int val) // 对应的隐式delete { cout << "delete: " << msg.c_str() << " " << val << endl; return ::operator delete(ptr); } }; MyClass *ptr1 = new("creating object...", 2) MyClass; // 调用方法 ::delete ptr1; // 没有重载显式delete,所以要调用::delete</code>程序可以调用::new和::delete访问全局的new或delete,但是除非有必要,不建议这样做。
[修改于 9年7个月前 - 2015/05/25 01:16:34]
引用 drzzm32:小教程可能不会有,但是c++ primer这种合格的教材是一定会有的。
居然能用new。。。似乎大部分教材并未说到C++有new关键字,倒是我有次把C++当成C#,做类初始化,new蓝了。。。
在特定内存上构造看起来是占用了char型变量的内存空间?
引用 drzzm32:我觉得那个在局部char[]里placement new的用法只是为了演示。
居然能用new。。。似乎大部分教材并未说到C++有new关键字,倒是我有次把C++当成C#,做类初始化,new蓝了。。。
在特定内存上构造看起来是占用了char型变量的内存空间?
引用 金星凌日:placement new也就是这个用途。一般来说用不着placement new
我觉得那个在局部char[]里placement new的用法只是为了演示。
placement new我只用过一次,是调用Lua的API。Lua的C API中有一个函数返回一个由Lua虚拟机管理的内存的指针,如果要给里面放C++的类实例,...
引用 drzzm32:和c#中的new不一样的是,c++中的new返回的是指针,而且必须手动delete。
居然能用new。。。似乎大部分教材并未说到C++有new关键字,倒是我有次把C++当成C#,做类初始化,new蓝了。。。
在特定内存上构造看起来是占用了char型变量的内存空间?
引用 金星凌日:忘记了,已加上全局说明符。。。
你最后那段代码g++编译通不过,提示“no suitable ‘operator delete’ for ‘MyClass’”。
此外,我记得C++标准是禁止重载placement new操作符的。
引用 金星凌日:C++标准不允许全局重载placement new,因为这个函数被定义为inline。但允许在类中重载。
你最后那段代码g++编译通不过,提示“no suitable ‘operator delete’ for ‘MyClass’”。
此外,我记得C++标准是禁止重载placement new操作符的。
时段 | 个数 |
---|---|
{{f.startingTime}}点 - {{f.endTime}}点 | {{f.fileCount}} |
200字以内,仅用于支线交流,主线讨论请采用回复功能。