我也喜欢@eq- 的回答,但除了动态内存分配之外,您还可以尝试放置新的。(当我说“尝试”时,我并不是说这是做事的方式,而是更像这样更值得深思。我不是想把你引向一个曲折的小通道迷宫,都一样。)
char mem[sizeof(CRectangle)] alignas(CRectangle);
CRectangle *prect = new (mem) CRectangle(3, 4); // construct
std::cout
<< "rect area: " << prect->area()
<< std::endl;
prect->~CRectangle(); // destruct
在使用自定义分配器时,您通常会使用placement new。可以出于各种原因使用自定义分配器,但在我的工作中,它通常用于预分配策略(例如池分配器或具有严格内存配置的嵌入式系统)。在这种情况下,放置 new 用于初始化具有自动存储类的内存。与您的原始rect
对象一样,当代码超出范围时,该对象的内存将变得无效。但是,CRectangle
构造函数可能会执行需要清理的初始化,因此在内存超出范围之前会显式调用析构函数。
请注意,您不能使用auto_ptr
for prect
,因为在指针上调用 delete 将是未定义的(因为内存不是动态创建的)。shared_ptr
如果您将自定义删除器传递给构造函数,则可以使用。unique_ptr
如果您在第二个模板参数中传入自定义删除器,则可以使用。自定义删除器只是对析构函数进行显式调用,以便智能指针在代码超出范围时自动进行清理工作。
template <typename T>
struct placement_delete {
void operator () (T *t) const { t->~T(); }
};
char mem2[2][sizeof(CRectangle) alignas(CRectangle);
std::shared_ptr<CRectangle>
sprect(new (mem2[0]) CRectangle(2, 3), placement_delete<CRectangle>());
std::unique_ptr< CRectangle, placement_delete<CRectangle> >
uprect(new (mem2[1]) CRectangle(3, 4));
该new
调用可能会引发std::bad_alloc
异常。由于它未被捕获,因此您的程序将在抛出异常并返回错误结果后立即终止。如果你想优雅地处理异常,你可以使用try
andcatch
阻塞。
CRectangle *prect;
try {
prect = new (mem) CRectangle(3, 4);
} catch (std::bad_alloc) {
// do something about it?
abort();
}
学习用,abort
还行。它可以让您练习捕获异常,但可以让您在分析由于abort
. (在 UNIX 上,这通常是一个核心文件。)