c++ - 有没有办法强制实例只在堆栈上?

标签 c++ c++11 c++14 automatic-storage

我有一个 C++ 类,我只希望它在堆栈上被实例化。我正在使用 api 访问以另一种(解释)语言开发的内容,该语言带有自己的垃圾收集。该语言中的机制足以将它找到的任何引用的内容单独留在堆栈上,并且由于该本地类包含这样的引用,因此对于正确的行为至关重要的是,它所执行的本地 C++ 类的用户永远不要尝试在其他任何地方分配它的实例。

注意,我不仅想禁止我的类的实例被分配新的(如果这就是我需要做的,我可以重载类的 new 运算符并将其设为私有(private),或自 C++11 起显式删除它),但也不允许该类的任何静态或可能的全局实例。安全地实例化这个类的唯一有效方法应该是在堆栈上,我想以某种方式保证这一点。据我所知,将 new 设为私有(private)或删除它也不会阻止另一个类被声明为我的类作为成员变量,并且该类的实例被分配在堆上。

我现在的管理方式是将“本地”一词作为类名称的一部分,作为对用户的友好提醒,该实例仅用于堆栈,但当然,这实际上不是由编译器或任何其他机制强制执行的,我更喜欢更具可执行性的解决方案。

理想情况下,我想在编译时确保这一点,如果使用不正确,编译会失败。如果这根本不可能,那么在构造实例时在运行时抛出异常仍然是可接受的回退。在 C++11 或 C++14 中工作的解决方案很好。

请注意,这个问题绝对this 相同。一个,它只想用 new

防止分配

最佳答案

免责声明:据我所知,“堆栈”不是 c++ 标准的一部分,我们有 ASDV(自动存储持续时间变量)。 ABI 可能会定义堆栈。请注意,有时这些是在寄存器中传递的,我认为在您的情况下是可以的。

定义一个CPS(continuation-passing style)工厂方法:

class A {
public:
   template<typename F, typename... Args>
   static auto cps_make(F f, Args&&... args) {
      return f(A(std::forward<Args>(args)...));
   }
private:
   A(/* ... */) {}
   A(const A&) = delete;
   A(A&&) = delete;
};

用法:传递一个带 A 的 lambda 和 A 的 ctor 参数。例如

return A::cps_make([&](A a) {
   /* do something with a */
   return true;
});

函数参数始终是内部的 ASDV。

代码是如何工作的:cps_make 接受一个仿函数(通常是一个 lambda),它接受一个给定类型的实例;和可选的ctor参数。它创建实例(通过将任何可选参数转发给 ctor),调用仿函数并返回仿函数返回的内容。由于仿函数可以是 C++11 中的 lambda,因此不会破坏正常的代码流。

CPS 的美妙之处在于,您只需在 C++14 中使用自动 lambda 即可拥有静态多态性:您的 cps_make() 可以创建几乎任何您想要的东西(层次结构、变体、任何等等)。然后为封闭的层次结构节省虚拟开销。你甚至可以有一个用于正常流程的 lambda,如果 ctor 会失败,则可以有一个;当异常不可行时,这很方便。

缺点是,目前你不能在 lambda 中直接使用外部作用域的控制流语句。/* 提示:我们正在努力。 */

关于c++ - 有没有办法强制实例只在堆栈上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43506853/

相关文章:

c++ - 从外部函数访问外部结构属性

c++ - 在 ACE 6.1 中找不到 ACE_RCSID

c++ - 无法在 C++ 中调用派生类函数

c++ - 将 char 数组传递给函数模板,以便 gcc 可以知道它是文字?

c++ - 如何为基础类型 int 的枚举专门化一个类?

c++ - C++14 是否向 C++ 添加了新关键字?

c++ - 从抽象类创建链

c++ - 为什么有专门为未初始化内存定义的 C++ 算法?

c++ - std::numeric_limits::quiet_NaN double/float 可以存储一些额外信息吗

c++ - 是否可以在 Xcode 5.1 中使用 std::make_unique?