C++20:常量引用的文字初始化的内存分配

C++20 : Memory allocation of literal initialization of const references

提问人:LastStarDust 提问时间:6/28/2022 更新时间:6/29/2022 访问量:159

问:

我正在尝试使用工厂设计模式优化一段代码的执行速度。

工厂将生成一个类的许多对象,这些对象具有一些成员,这些成员在整个程序执行过程中是恒定的,而一些成员则不是。我总是用文字初始化常量成员。

我的问题是,如何管理常量成员的记忆?编译器是否可以优化代码,以便在每次创建/销毁新对象时都不会分配/释放此内存?

理想情况下,我希望文本驻留在一个固定的内存片段上,并且只对每个新对象提供对该内存的引用。我想避免使用全局变量。

class Test {
private:
  const std::string &name_;
  int value_;
public:
  Test(const std::string &name, int value) : name_(name), value_(value) {}
};

int main() {
  Test test1("A", 1);
  Test test2("B", 2);
  Test test3("B", 3);
  Test test4("A", 4);
  Test test5("B", 5);
  // etc ...
}

PS1的。请注意,在代码片段中未显示工厂模式实现。

PS2的。假设 Linux 上的 GCC 11.2.0

C++ 内存管理 C++20 常量引用

评论

6赞 Alan Birtles 6/28/2022
我认为您的代码具有未定义的行为,因为它存储了对临时 .为什么不直接存储或使用(但不是引用,否则你会遇到同样的问题)std::stringconst char*std::string_viewstd::string_view
1赞 Quimby 6/28/2022
“实际上,我希望文字驻留在一个固定的内存片段上,并且只对每个新对象提供对这个内存的引用。我想避免使用全局变量。如果你有一个固定的记忆,你不妨给它命名。
2赞 molbdnilo 6/28/2022
不可变的全局数据是没有问题的。全局变量的问题不在于范围,而在于共享的可变状态。如果从字面上关心范围,请使用命名空间。
0赞 LastStarDust 6/28/2022
@AlanBirtles 谢谢你指出这种可能性。但是,假设我的理解是正确的,似乎将临时对象的生存期延长到引用它的常量引用的生存期是一个官方的 C++ 功能
1赞 Alan Birtles 6/28/2022
在您的链接中,请参阅。这就是为什么我说,关于常量参考寿命延长的规则很复杂,所以我发现避免它更简单Please note that this does not apply to const reference class members, only to local const references!I think

答:

0赞 user3188445 6/29/2022 #1

获得你想要的东西的最简单方法是做一个:name_const char *

class Test {
private:
  const char *const name_;
  int value_;
public:
  Test(const char *name, int value) : name_(name), value_(value) {}
};

int main() {
  Test test1("A", 1);
  Test test2("B", 2);
  Test test3("B", 3);
  Test test4("A", 4);
  Test test5("B", 5);
  // etc ...
}

这是有效的,因为编译器将优化内存中的字符串,因此在这种情况下,您不需要内存中的多个副本。"A"

不幸的是,您提供的代码将不起作用,并留下一个悬而未决的引用。原因是,当引用绑定到对象的临时实例化时,何时延长临时对象生存期的规则会扩展。但是,在代码中,temporary 首先绑定到 ,然后绑定到 。因此,暂时物化的东西将在分号处被销毁。std::stringnamenamename_std::string

使用 a 的一个缺点是,如果要在字符串中嵌入 NUL 字符 (),您将丢失长度信息。一个可能的解决方法是将字符串的长度作为模板参数,如下所示:const char *'\0'

class Test {
private:
  const char *const name_;
  const std::size_t size_;
  int value_;
public:
  template<std::size_t N>
  Test(const char name[N], int value)
    : name_(name), size_(N-1), value_(value) {}
};

评论

0赞 jxh 6/29/2022
也许使用 .string_view
0赞 user3188445 6/29/2022
使用一个似乎容易出错,以防有人传入 .也许如果构造函数是?string_viewstd::stringconsteval