【问题标题】:Determine whether any of class member can do heap allocation?确定是否有任何类成员可以进行堆分配?
【发布时间】:2022-10-04 19:35:40
【问题描述】:

我遇到了以下问题。
鉴于我们有class Foo,有没有办法(trait/meta-program/trick/...)来确定(编译时间)是否有任何类会员可以做堆分配吗?

像这样的东西:

class A
{
    int a = 5;
    std::array<int,10> arr;
    ...
};

class B
{
    char c;
    std::string s;
    ...
};

can_allocate&lt;A&gt; 产生错误
can_allocate&lt;B&gt; 为真

如果字符串超过小字符串优化边界,std::string 可能会进行分配。

有谁知道这种语言功能或一些自定义实现?或者它甚至无法实现?

【问题讨论】:

  • C++ 代码无法检查自身,因此(在程序本身内部)无法知道函数是否可以分配堆内存。为此,您需要其他外部静态分析器。或外部动态运行时分析器,用于您没有源代码的功能。
  • 我有点希望某些特征可以在成员中进行递归搜索,并看到任何人都使用过 operator new、operator & 等。这不是痉挛,而是类似
  • 您试图用这个问题解决的实际问题是什么?
  • 我们需要实现一组将写入共享内存的类。因此需要扁平结构/无分配。所以我们要在编译时禁止潜在的灾难。
  • 假设你有一个非最终的虚函数。对于没有看到编译时的实现,您会返回 truefalse 吗?

标签: c++ language-lawyer dynamic-memory-allocation traits


【解决方案1】:

这不是一个完整的答案,但如果你可以使用 c++20 并且你可以忍受一些限制(即它只适用于文字类型您可能可以利用在 c++20 中允许在 constexpr 上下文中分配内存的事实,只要它们不会冒泡到运行时代码中。因此,也许您可​​以按照以下方式构建一些东西:

class A
{
    int a = 5;
    std::array<int,10> arr;
};

class B
{
    char c{};
    std::string s{};
};

template<typename T>
consteval T check_me() {
    return {};
}

int main() {

    check_me<A>();
    check_me<B>(); // doesn't compile
}

Compiler Explorer

似乎 msvc 错误地没有拒绝编译它,但我认为这是一个编译器错误(?)。

另外,请注意,此代码仅检查默认构造函数,而不检查分配是否可能发生在 T 的任何成员函数或其成员中。

【讨论】:

  • 只要std::string 对象实际上不执行内存分配,对check_me 的调用就有效。因此,它可能适用于默认构造,或者只要字符串足够小以适合小字符串缓冲区,这取决于std::string 的编译时部分是如何实现的。那不是错误。只是未指明它是否会通过。
  • @user17732522 你是对的。我怀疑这一点,我什至用一些字符初始化它来测试它;仍然在 MSVC 中编译,所以我认为它是一个错误,但现在我再次尝试使用更多字符,是的,现在它按预期工作。
猜你喜欢
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
相关资源
最近更新 更多