gpt4 book ai didi

c++ - 静态常量成员初始化和模板(与静态函数相比)——这是如何工作的?

转载 作者:太空狗 更新时间:2023-10-29 20:45:10 29 4
gpt4 key购买 nike

我知道 C++ 标准说(第 9.4.2 节第 4 段)整型或枚举类型的静态成员变量可以在类内部提供初始化程序,但这需要在类外部定义该成员(在一个编译单元)。即,您需要执行以下操作:

class A
{
public:
static const int X = 10;
};

// this is required by the standard
const int A::X;

我已经看到(并且我已经在其他地方看到过)一些编译器会让你在没有类外定义的情况下逃脱。这适用于 OS X 上的 gcc 4.2.1:

#include <iostream>    

class A
{
public:
static const int X = 10;
};

int main(int argc, char** argv)
{
std::cout << A::X << std::endl;
return 0;
}

我最近遇到了一个错误,有人这样做了,但是他们在模板函数中使用了成员变量(确切地说是 std::max),它不会编译,提示 undefined symbol A::X。即,这不起作用:

#include <iostream> 
#include <algorithm>

class A
{
public:
static const int X = 10;
};

int main(int argc, char** argv)
{
std::cout << std::max(1, A::X) << std::endl;
return 0;
}

在类外定义中重新添加使其工作。

这是一个学术问题,但我想知道为什么会发生这种情况。特别是关于如果我们用静态函数替换静态成员变量的事实 (static const int X = 10; 变成 static int X(), A::X 变为 A::X()),然后它将在没有类外定义的情况下编译。我提到模板的原因是因为 std::max 是模板化的,而其他模板化函数会重现相同的行为。它可能与模板没有特别相关,但我想了解为什么模板会导致它们的行为。我认为这一定与模板和静态成员的编译/实现方式有关?

PS - 我在 github 上发布了一些最少的代码

最佳答案

它会在没有定义的情况下编译。

如果静态成员变量odr-used,则在链接时需要定义。 (如果编译器在每次引用它时设法替换它的实际值,它就不会被 odr-used。另一方面,获取它的地址肯定会使其 odr-used )

这是完整的规则(第 9.4.2 节 [class.static.data]):

If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. — end note ] The member shall still be defined in a namespace scope if it is odr-used in the program and the namespace scope definition shall not contain an initializer.

来自第 3.2 节 [basic.def.odr]:

A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression and the lvalue-to-rvalue conversion is immediately applied.

满足出现在常量表达式中的要求,所以一切都取决于它是用作左值还是右值

std::max 采用左值引用,因此不会立即进行左值到右值的转换。


与模板的唯一交互是可能有多个等效定义,链接器会选择其中一个。在您的情况下,没有模板,因此多个定义会产生“符号多重定义”类型的错误。

当您忘记提供定义时,这两种情况(模板类成员和普通类成员)都会给出相同的错误:“undefined symbol”。

关于c++ - 静态常量成员初始化和模板(与静态函数相比)——这是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11336173/

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