这会限制 class 仅在当前帧中有生命周期吗?

Would this restrict the class to be have a lifetime in the current frame only?

我想限制特定的 class 只能在堆栈上创建(而不是通过分配)。这样做的原因是在堆栈上,生命周期最后开始的对象将最先被销毁,我可以创建一个层次结构。我是这样做的:

#include <cstddef>
#include <iostream>

class Foo {
public:
  static Foo createOnStack() {
    return {};
  }
  ~Foo () {
    std::cout << "Destructed " << --i << std::endl;
  }

protected:
  static int i;
  Foo () {
    std::cout << "Created " << i++ << std::endl;
  }
  Foo (const Foo &) = delete;
};
int Foo::i = 0;

构造函数通常应该压入层次堆栈,而析构函数弹出它。我在这里将其替换为概念证明。现在,使用此类对象的唯一方法是将其存储在临时引用中,如下所示:

int main() {
  Foo && a = Foo::createOnStack();
  const Foo& b = Foo::createOnStack();
  return 0;
}

我现在的问题是,C++ 标准的安全性如何?是否还有一种方法可以合法地在堆上创建 Foo 或将其从您的函数传递到另一个框架(又名 return 它从您的函数)而不 运行 进入未定义的行为?


编辑:link 例如 https://ideone.com/M0I1NI

撇开 protected 后门不谈,C++17 copy elision 两种 方式破坏了它:

#include<iostream>
#include<memory>

struct S {
  static S make() {return {};}
  S(const S&)=delete;
  ~S() {std::cout << '-' << this << std::endl;}
private:
  S() {std::cout << '+' << this << std::endl;}
};

S reorder() {
  S &&local=S::make();
  return S::make();
}

int main() {
  auto p=new S(S::make()),q=new S(S::make());  // #1
  delete p; delete q;
  reorder();                                   // #2
}
  1. new的用法很明显,
  2. C++17 还允许纯右值通过堆栈帧传播,这意味着 local 可以在 return 值之前创建并在 return 值被销毁时被销毁还活着。

请注意,在 localS 类型但 return 值是其他一些(可移动的)类型。一般来说,您不能假设即使是自动对象生命周期也能正确嵌套。