为什么不能将类内初始化的const const std :: string`设为静态成员 [英] Why can't I make in-class initialized `const const std::string` a static member

查看:426
本文介绍了为什么不能将类内初始化的const const std :: string`设为静态成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下工作代码:

#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';
}

是否有充分的理由说明为什么不可能使测试成为静态常量?我确实了解c ++ 11之前的版本受标准限制。我认为c ++ 11引入了类内初始化,以使其更加友好。相当一段时间以来,我也没有这种语义可用于整数类型。

Is there a good reason why it is not possible to make the test a static const ? I do understand prior to c++11 it was constrained by the standard. I thought that c++11 introduced in-class initializations to make it a little bit friendlier. I also not such semantic are available for integral type since quite some time.

当然,它可以与形式的类外初始化一起使用const std :: string A :: test = 42;

我想,如果可以将其设为非静态,则问题在于两者之一。初始化它超出类范围(通常在对象实例化期间创建 const )。但是,如果您要创建一个独立于该类其他成员的对象,我认为这不是问题。第二个是对静态成员有多个定义。例如。如果将它包含在几个 .cpp 文件中,并登陆到多个目标文件中,则链接器在将这些对象链接在一起(例如,合并到一个可执行文件)时会遇到麻烦,例如它们将包含相同符号的副本。据我了解,这完全等同于以下情况:在标题的类声明下提供超出类别的权限,然后在多个位置包含此公共标题。我记得,这会导致链接器错误。

I guess that, if you can make it non-static, then the problem lies in one of the two. Initializing it out-of-class scope (normally consts are created during the instantiation of the object). But I do not think this is the problem if you are creating an object independant of any other members of the class. The second is having multiple definitions for the static member. E.g. if it were included in several .cpp files, landing into several object-files, and then the linker would have troubles when linking those object together (e.g. into one executable), as they would contain copies of the same symbol. To my understanding, this is exactly equal to the situation when ones provides the out-of-class right under the class declaration in the header, and then includes this common header in more than one place. As I recall, this leads to linker errors.

但是,现在,处理此错误的责任已移交给用户/程序员。如果要使用静态 的库,则需要提供一个类外的定义,将其编译成单独的对象文件,然后将所有其他对象链接到

However, now the responsibility of handling this is moved onto user/programmer. If one wants to have a library with a static they need to provide a out-of-class definition, compile it into a separate object file, and then link all other object to this one, therefore having only one copy of the binary definition of the symbol.

我阅读了我们是否仍需要单独定义静态成员,即使它们是在类中初始化的也是如此定义?为什么不能在类中初始化非常量静态成员或静态数组?

我仍然想知道:


  1. 这仅仅是标准的东西,还是背后有更深层次的推理?

  2. 可以解决此问题吗? constexpr 和用户定义的
    点亮道德机制。 clang和g ++都说变量不能具有非文字类型。也许我可以做一个。 (也许出于某种原因,这也是一个坏主意)

  3. 链接器只包含一个
    符号真的是一个大问题吗?由于它是静态const ,因此应全部为二进制精确的
    不可变副本。

  1. Is it only a standard thing, or there is deeper reasoning behind it?
  2. Can this be worked-around with the constexpr and user-defined literals mechanisms. Both clang and g++ say the variable cannot have non-literal type. Maybe I can make one. (Maybe for some reason its also a bad idea)
  3. Is it really such a big issue for linker to include only one copy of the symbol? Since it is static const all should be binary-exact immutable copies.

如果我遗漏或误解了某些内容,请发表评论。

Plese also comment if I am missing or missunderstanding something.

推荐答案

您的问题分为两部分。标准怎么说?

Your question sort of has two parts. What does the standard say? And why is it so?

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

For a static member of type const std::string, it is required to be defined outside the class specifier and have one definition in one of the translation units. This is part of the One Definition Rule, and is specified in clause 3 of the C++ standard.

但是为什么?

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

The problem is that an object with static storage duration needs unique static storage in the final program image, so it needs to be linked from one particular translation unit. The class specifier doesn't have a home in one translation unit, it just defines the type (which is required to be identically defined in all translation units where it is used).

常量积分不需要存储的原因是,编译器将其用作常量表达式并在使用时内联。

The reason a constant integral doesn't need storage, is that it is used by the compiler as a constant expression and inlined at point of use. It never makes it to the program image.

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

However a complex type, like a std::string, with static storage duration need storage, even if they are const. This is because they may need to be dynamically initialized (have their constructor called before the entry to main).

您可能会认为编译器应使用静态对象存储有关对象的信息存储在每个使用它们的翻译单元中的持续时间,然后链接器应在链接时将这些定义合并到程序映像中的一个对象中。我之所以无法做到这一点,是因为它可能需要链接程序提供过多的信息。

You could argue that the compiler should store information about objects with static storage duration in each translation unit where they are used, and then the linker should merge these definitions at link-time into one object in the program image. My guess for why this isn't done, is that it would require too much intelligence from the linker.

这篇关于为什么不能将类内初始化的const const std :: string`设为静态成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆