是否有一种模式可以在退出范围时自动调用堆栈中 placement-new 初始化对象的析构函数?我想跳过记住要明确调用析构函数的需求。或者,是否有不同于 placement-new 的方法来构造具有可变大小data []尾部的基于堆栈的对象?我用的是g ++。
/* g++ f.cpp -o f.exe */
/* 8< --- f.cpp ---- */
#include <stdio.h>
#include <stdlib.h>
#include <string>
class aclass {
public:
aclass(int size) : size_(size) {};
~aclass() { /* do something */ };
int size_;
char data[0];
};
void f(int size)
{
char v[sizeof(aclass) + size];
aclass *p = new(static_cast<void*>(&v)) aclass(size);
p->~aclass();
}
int main(int argc, char **argv)
{
f(10);
f(100);
return 0;
}
答案 0 :(得分:3)
您可以创建一个包装类,如下所示:
template <typename T>
class Foo {
private:
T *m_ptr;
public:
Foo(void *area, int size) {
m_ptr = new(area) T(size);
}
Foo(const Foo &) = delete;
~Foo() {
m_ptr->~T();
}
void operator=(const Foo &) = delete;
T *operator->() {
return m_ptr;
}
};
用法:
void f(int size) {
char v[sizeof(aclass)+size];
Foo<aclass> p(v, size);
p->doSomething(); // call a function from aclass
}
请注意,您正在使用GCC扩展名,因为size
不是编译时常量。
如果这是一个编译时常量,则可以将v
放入Foo
中(并且size
将是模板参数),因此f
会更简单
答案 1 :(得分:1)
已经有一个标准的包装模板类可以执行此操作-std::unique_ptr
。
请注意评论中的注意事项
#include <cstdio>
#include <cstdlib>
#include <string>
#include <memory>
class aclass {
public:
aclass(int size);
~aclass();
int size_;
char data[0]; // this is illegal in standard c++
};
// deleter which only calls destructor, does not deallocate
struct inplace_deleter
{
template<class T>void operator()(T* p) const noexcept
{
p->~T();
}
};
void f(int size)
{
// VLAs are not standard c++. This is a compiler extension on gcc.
char v[sizeof(aclass) + size];
using ptr_type = std::unique_ptr<aclass, inplace_deleter>;
auto p = ptr_type(new(&v) aclass(size));
// auto deleted
}
int main()
{
f(10);
f(100);
return 0;
}