如何创建一个C ++类,其对象只能作为 放在堆栈上,作为单个实例,但
std::vector
(或其他标准容器),并且无论在哪里分配,都不。注意:How do I prevent a class from being allocated via the 'new' operator? (I'd like to ensure my RAII class is always allocated on the stack.)询问如何避免免费存储,但这只是答案的一半。我想(?)对于容器,可以使用placement-new运算符做类似的事情,但是对于数组和数据成员情况有什么用呢?
限制应该是编译器强制执行的。 (没有运行时检查。)
以示例:
class User {
...
StackOnly m; // may be OK (depending if below implementable)
};
void f() {
StackOnly obj; //ok
StackOnly arrobj[42]; // fail!
StackOnly* pObj = new StackOnly(); // fail!
std::vector<StackOnly> v; // fail!
User obj; //ok
User arrobj[42]; // fail!
User* pObj = new StackOnly(); // fail!
std::vector<User> v; // fail!
}
答案 0 :(得分:4)
以下课程仅允许:const X& x = X::MakeInstance();
或class X
{
public:
X(const X&) = delete;
X(X&&) = delete;
X& operator =(const X&) = delete;
X& operator =(X&&) = delete;
public:
static X MakeInstance() { return {}; }
static void* operator new (size_t) = delete;
static void* operator new[] (size_t) = delete;
static void operator delete (void*) = delete;
static void operator delete[](void*) = delete;
private:
X() = default;
};
使用:
.children()
答案 1 :(得分:1)
我们可以做的是一些非便携式黑客攻击,我们可以像这样获得堆栈指针:
volatile char var, *approximate_stack_ptr = &var;
我们在对象的构造函数中执行此操作。
然后我们可以检查对象本身的地址(this
指针)是否在approximate_stack_pointer
的4096字节之内;即。
// formally undefined behavior here, but chances are good
// it will work with many compilers:
ptrdiff_t delta = (char *) this - approximate_stack_ptr;
// Then, check that delta is between -4096 and 4096
4096的价值是慷慨的,因为它可以;实际的delta可能要小得多。但是,没有必要严格要求。未以任何有效方式在堆栈上定义的对象将远离堆栈指针;远远超过4096字节。 (除非我们正在处理一个非常小的嵌入式系统实现,其中4096就像是可寻址空间的一半。)