Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ ODR使用行为基本原理_C++_Language Lawyer_Constexpr - Fatal编程技术网

C++ ODR使用行为基本原理

C++ ODR使用行为基本原理,c++,language-lawyer,constexpr,C++,Language Lawyer,Constexpr,为什么通过常量引用传递参数总是意味着使用了ODR对象?我理解,因为标准是这样定义的,但为什么它至少对整型常量不例外呢 例如(我自己的例子来自几个小时前的答案): struct{ 静态constexpr int i=42; }; 无效检查(const int&z); int main(){ check(T::i);//假设在两个tu中发生相同的调用。函数check可以采用z的地址,并且标准保证在两个调用中看到相同的地址 除了分配一个存储位置并将i放在那里之外,您将如何实现这一点?这正是ODR所说的

为什么通过常量引用传递参数总是意味着使用了ODR对象?我理解,因为标准是这样定义的,但为什么它至少对整型常量不例外呢

例如(我自己的例子来自几个小时前的答案):

struct{
静态constexpr int i=42;
};
无效检查(const int&z);
int main(){

check(T::i);//假设在两个tu中发生相同的调用。函数
check
可以采用
z
的地址,并且标准保证在两个调用中看到相同的地址

除了分配一个存储位置并将
i
放在那里之外,您将如何实现这一点?这正是ODR所说的

然而,该标准对示例(2)没有问题

因为在(2)的情况下,我们正在创建一个类型为
int const&
的临时变量,它绑定到prvalue
42

但是
T::i
不是右值,它是左值-所以我们不会尝试创建一个临时值,我们会尝试绑定到实际对象。但是编译器怎么知道
T::i
是一个左值,您不希望最终为其提供定义,在这种情况下,您真正的意思是构造一个临时值创建并复制它?
constexpr
不是类型的一部分,
i
的类型只是
int-const
。您可能需要跨越很多障碍,甚至试图想出一个措辞,正确地豁免您的
静态constexpr int i
,但豁免某些成员
const-int i

所有这些都是为了解决什么问题?您可以通过
+T::i
手动执行左值到右值的转换,并实现相同的功能。或者为
T::i
提供定义


ODR规则足够复杂了,你需要一个令人信服的理由在其中钻一个洞。如果你告诉我们什么是< <代码> x>代码>,什么是<代码>检查< <代码>,你写的东西会更有意义:简单的回答:席西不知道为什么人们否决了这个问题。我也奇怪为什么它主要是意见?n-based'-没有什么是基于观点的,@Barry解释得很好。最简单的解决方案就是通过值传递。@AlanStokes,我想这里的人理解示例的价值,而不是真实代码。在真实代码中,
check()
将是一个模板,按值传递将是不合适的。这并不能回答我的问题。如果地址是唯一的问题,它可以像处理文本一样工作。不,它不能。
检查(1)
从两个不同的TU调用可以传递两个不同的地址;
检查(t::i)
不是。而
check
可以看出区别。我们可以为
constexpr
和地址创建一个例外,并制定与文本相同的规则?我认为,我发现@Barry answer在右值对右值方面更具说服力。所以你可以说
constexpr
变量的地址在不同的表达式中可能不同离子?这对我来说根本不好。这意味着添加一个
constexpr
可能会破坏工作代码。坏的或好的都可以基于某个东西。为什么不好?我发现它是好的。“工作代码”是什么意思?Pre-constexpr代码没有constexpr,所以不会破坏遗留行为。编写新代码时会考虑到这一点。Act事实上,当你用左值对右值来表达它时,它现在是有意义的。我不认为这是定义的原因。酷,我现在知道了两个你可以使用一元+的真正模糊的东西!(整体提升是另一个。)@Barry谢谢!尽管我不确定是笑还是哭。
struct T {
    static constexpr int i = 42;
};

void check(const int& z);

int main() {
    check(T::i); // <- 1
    check(42); // <- 2
}