gpt4 book ai didi

c++ - 为什么我不能使类内初始化 `const const std::string` 成为静态成员

转载 作者:可可西里 更新时间:2023-11-01 17:56:12 26 4
gpt4 key购买 nike

我有以下工作代码:

#include <string>
#include <iostream>

class A {
public:
const std::string test = "42";
//static const std::string test = "42"; // fails
};

int main(void){
A a;
std::cout << a.test << '\n';
}

为什么不能使测试成为 static const 有充分的理由吗?我确实了解在 c++11 之前它受到标准的约束。我认为 c++11 引入了类内初始化以使其更友好一些。很长一段时间以来,我也没有这样的语义可用于整数类型。

当然,它适用于 const std::string A::test = "42";

形式的类外初始化

我猜想,如果您可以使它成为非静态的,那么问题就出在两者之一上。在类外范围内初始化它(通常 const 是在对象实例化期间创建的)。但是,如果您要创建一个独立于该类的任何其他成员的对象,我认为这不是问题。第二个是对静态成员有多个定义。例如。如果它被包含在几个 .cpp 文件中,进入几个目标文件,那么链接器在将这些对象链接在一起时会遇到麻烦(例如链接到一个可执行文件中),因为它们将包含相同的符号。我的理解,这正好等于在header中class声明下提供了out-of-class权限,然后在不止一个地方包含了这个common header。我记得,这会导致链接器错误。

但是,现在处理这个的责任转移到了用户/程序员身上。如果一个人想要一个带有 static 的库,他们需要提供一个类外定义,将它编译成一个单独的对象文件,然后将所有其他对象链接到这个对象,因此只有符号二进制定义的一份拷贝。

我阅读了 Do we still need to separately define static members, even if they are initialised inside the class definition? 中的答案和 Why can't I initialize non-const static member or static array in class? .

我还想知道:

  1. 这只是一个标准的东西,还是背后有更深层次的原因?
  2. 这可以通过 constexpr 和用户定义来解决吗文字机制。 clang 和 g++ 都说变量不能有非文字类型。也许我可以做一个。 (也许出于某种原因这也是一个坏主意)
  3. 链接器只包含一个拷贝真的是个大问题吗?符号?因为它是 static const 所有都应该是二进制精确的不可变拷贝。

如果我遗漏或误解了什么,也请发表评论。

最佳答案

您的问题分为两部分。标准怎么说?为什么会这样?

对于const std::string类型的静态成员,要求定义在类说明符之外,并且在其中一个翻译单元中有一个定义。这是单一定义规则的一部分,并在 C++ 标准的第 3 条中指定。

但为什么呢?

问题在于,具有静态存储持续时间的对象需要在最终程序镜像中进行唯一的静态存储,因此需要从一个特定的翻译单元进行链接。类说明符在一个翻译单元中没有归属地,它只是定义类型(需要在使用它的所有翻译单元中进行相同的定义)。

常量积分不需要存储的原因是它被编译器用作常量表达式并在使用时内联。它永远不会出现在程序图像中。

然而,复杂类型,如 std::string,具有静态存储持续时间需要存储,即使它们是 const。这是因为它们可能需要动态初始化(在进入 main 之前调用它们的构造函数)。

您可能会争辩说,编译器应该在使用它们的每个翻译单元中存储有关具有静态存储持续时间的对象的信息,然后链接器应该在链接时将这些定义合并到程序镜像中的一个对象中。我猜测为什么没有这样做,是因为它需要链接器提供太多智能。

关于c++ - 为什么我不能使类内初始化 `const const std::string` 成为静态成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17351870/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com