gpt4 book ai didi

c++ - 是否使用静态 constexpr 变量 odr?

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

给出下面的代码,是否使用了 Foo::FOO1 ODR?

#include <iostream>
#include <map>
#include <string>

class Foo
{
public:
static constexpr auto FOO1 = "foo1";
void bar();
};

void Foo::bar()
{
const std::map<std::string, int> m = {
{FOO1, 1},
};
for (auto i : m)
{
std::cout << i.first << " " << i.second << std::endl;
}
}

int main()
{
Foo f;
f.bar();
return 0;
}

使用 -O1 或更高版本编译代码,没问题,但如果使用 -O0 编译,我会出现以下错误(参见 coliru example :

undefined reference to `Foo::FOO1'

表示它是 ODR 使用的。是哪个?


我知道上面的代码使用 -O 构建得很好,但是在 a real (and more complex) case 中:

  • 代码可以通过 -O2 正常编译和链接
  • 代码得到上面的undefined reference错误LinkTimeOptimization (-O2 -flto)

所以这表明优化 (-O) 和 LinkTimeOptimization (-flto) 都会影响 ODR 使用规则?这在 C++14 和 C++17 之间有变化吗?

最佳答案

规则是[basic.def.odr]/4 :

A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion to x yields a constant expression that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion ([conv.lval]) is applied to e, or e is a discarded-value expression ([expr.prop]).

第一部分显然是令人满意的(FOO1constexpr 所以左值到右值的转换确实产生了一个常量表达式而不调用非平凡函数),但第二部分是吗?

我们正在构建一个 map .相关constructor there需要 initializer_list<value_type> ,也就是说 initializer_list<pair<const string, int>> . pair有一个bunch of constructors ,但这里将调用的是:

template <class U1, class U2>
constexpr pair(U1&& x, U2&& y); // with U1 = char const*&, U2 = int

这里的重要部分是我们没有直接构建 string ,我们正在经历 pair 的这个转换构造函数,这涉及绑定(bind)对 FOO1 的引用.这是一个 odr 用途。这里没有左值到右值的转换,也不是丢弃值表达式。

基本上,当您获取某物的地址时,这是一个 odr-use - 它必须有一个定义。所以你必须添加一个定义:

constexpr char const* Foo::FOO1;

请注意,另一方面,这是:

std::string s = FOO1;

不会是一个 odr 用途。在这里,我们直接调用一个构造函数接受 char const*。参数,这将是左值到右值的转换。


在 C++17 中,我们在 [dcl.constexpr] 中得到了这个新句子:

A function or static data member declared with the constexpr specifier is implicitly an inline function or variable ([dcl.inline]).

这不会改变关于 odr-use 的任何内容,FOO1在您的程序中仍然使用 odr。但它确实使 FOO1隐式地是一个内联变量,因此您不必为它显式添加定义。很酷。


另请注意,仅因为程序编译和链接并不意味着缺少定义的变量未被 ODR 使用。

So it indicates that both optimizations (-O) and LinkTimeOptimization (-flto) would affect ODR-use rule?

他们没有。这样的优化很酷。

关于c++ - 是否使用静态 constexpr 变量 odr?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52251833/

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