我的 C++ 教授向我们展示了这个重载运算符 new 的示例(我认为这是错误的):
class test {
// code
int *a;
int n;
public:
void* operator new(size_t);
};
void* test::operator new(size_t size) {
test *p;
p=(test*)malloc(size);
cout << "Input the size of array = ?";
cin >> p->n;
p->a = new int[p->n];
return p;
}
这样对吗?
最佳答案
这绝对是“不对的”,因为它让我毛骨悚然。
因为 test
没有用户声明的构造函数,我认为它可以工作,前提是 test
的实例不是值初始化的(这会清除指针) .并且前提是你写了相应的operator delete
。
不过,这显然是一个愚蠢的例子——在重载的 operator new
中进行用户交互?如果在堆栈上创建了 test
的实例怎么办?还是复制的?或者在 C++03 中用 test *tp = new test();
创建?还是安置新的?几乎没有用户友好性。
必须使用构造函数 来建立类不变量(例如“我有一个要使用的数组”),因为这是涵盖所有这些情况的唯一方法。所以像这样分配一个数组是应该在构造函数中完成的事情,而不是在 operator new
中。或者更好的是,使用 vector
代替。
就标准而言——我认为由于该类是非 POD 的,因此允许实现在调用 operator new
并将其返回给用户之间涂写所有数据,因此即使小心使用也不能保证有效。不过,我不完全确定。可以想象你的教授已经运行了它(也许很多年前他第一次编写类(class)时),如果是的话它可以在他的机器上运行。在此类的特定情况下,没有明显的理由说明为什么实现要对内存执行任何操作。
I believe that is "wrong" because he access the object before the constructor.
我认为你在这一点上也是正确的 - 将从 malloc
返回的指针转换为 test*
并且访问成员是 UB,因为类 test
是非 POD(因为它具有私有(private)非静态数据成员)并且内存不包含该类的构造实例。不过,同样,我没有理由立即想到为什么一个实现会想要做任何阻止它工作的事情,所以如果在实践中它将预期值存储在我机器上的预期位置,我并不感到惊讶。
关于c++ - 在 operator new 中访问一个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4502728/