勘误:在C++语言层面,没有办法实现符合这种要求的类,即使将 new 和 delete 重载为私有,加有限定名字查找 :: ,优先查找全局的 operator new 和 operator delete,重载为私有的就毫无意义。就算把new和delete设置为= delete也不行。详见https://godbolt.org/z/nqs9Gcv6b。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

struct X{
int n{};
X() { puts("X()"); }
X(int v):n{v} {puts("X(int)");}
~X() { puts("~X()"); }
private:
void* operator new(size_t)noexcept {return nullptr;}
void operator delete(void*) {}
};

int main(){
X* p = ::new X(10);
std::cout<< p->n <<'\n';
::delete p;
}

vs运行报错,因为 msvc 有限定名字查找有 bug,gcc 和 clang 都可以直接使用。(已编辑)

另外,这个方法根本限制不了在创建静态或线程局部存储期的该类对象。实际下,这些存储期的对象都不在栈上。
在网上学习得知。一些近似的办法,但相当可能不符合题意:

  1. 完全限制该类的构造函数的访问,使得外部不得构造该类对象,而内部操作只在栈上构造该类对象。
  2. 生成不可移动或复制的 lambda 表达式闭包类型(需要至少 C++17)。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct Pinned {
    Pinned() = default;
    Pinned(const Pinned&) = delete;
    Pinned& operator=(const Pinned&) = delete;
    };

    int main()
    {
    auto pinned_lambda = [p = Pinned{}]{};
    // 此后不能在其他地方构造另一个与 pinned_lambda 拥有相同类型的对象
    }
    完全符合题目本意的做法基本上是不存在的,除非通过和操作系统交流,在构造函数中确定 this 是否指向系统划定的栈空间。
    有疑问或者想更深入了解可以看https://github.com/huihut/interview/issues/112