可以将* * *放在堆栈上的C ++类?

时间:2016-11-22 22:09:58

标签: c++ stl

如何创建一个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!
}

2 个答案:

答案 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就像是可寻址空间的一半。)