看不懂..............
#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>
上边出现了显式调用析构函数的语句,C++中析构函数是可以直接调用的。而构造函数却不能直接调用(直接调用的含义是新建临时值对象),需要使用new(void*)这种特殊方法。
// 单变量形式
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指向的对象数组
new和delete运算符的重载(operator new、operator delete)并不需要调用构造函数或析构函数,operator new只需分配内存,并返回内存块的起始地址,而operator 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
// 数组形式
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[]
比如以下代码可以让C++调用对应的隐式delete——#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>
如果在类中重载了一对new和delete,那么在new或delete这个类的对象时,C++只会在类中搜索new或delete,不会在全局搜索。所以,对于重载new或delete运算符的C++类,需要同时重载三种形式。
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
}
};
实际上operator new和operator new[]的参数数量并没有限制,形式可以为void* operator new(size_t, ...),只需要保证第一个参数size_t和返回值void*的类型正确即可。这些重载形式均可以用new(...)形式调用。但是也要注意,如果写了某一个new重载,那么还需要再写一个相对应形式的void operator delete(void*, ...)以处理构造函数抛出异常的情况,同样需要注意第一个参数void*和返回值void的类型正确。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
程序可以调用::new和::delete访问全局的new或delete,但是除非有必要,不建议这样做。
[修改于 9年8个月前 - 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操作符的。
200字以内,仅用于支线交流,主线讨论请采用回复功能。