给定代码片段:
struct S {
static const int var = 0;
};
int function(const int& rVar){
return rVar;
}
int main()
{
return function(S::var);
}
使用 gcc 5.4.0
编译:
g++ -std=c++17 main.cpp -o test
导致以下链接错误:
/tmp/ccSeEuha.o: 在函数 `main' 中:
main.cpp:(.text+0x15): 对 `S::var' 的 undefined reference
collect2:错误:ld 返回 1 退出状态
n4296
中的 §3.3
指出:
A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.20) 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 (4.1) is applied to e [bold-type formatting added], or e is a discarded-value expression (Clause 5).
问:为什么这里需要定义变量var
? var
不是表示出现在外部函数调用表达式的 potentially-evaluted 表达式 S::var
中的整数对象吗?通过引用获取一个参数,但最终对其应用了左值到右值的转换,因此不是如段落中所述odr-used?
最佳答案
but to which finally a lvalue-to-rvalue conversion is applied, and, thus isn't odr-used as stated in the paragraph?
我认为另一个表达式中的左值到右值转换是无关紧要的。在表达式 function(S::var)
中没有应用于子表达式 S::var
的左值到右值转换,因此异常(exception)不适用。
从常识的角度考虑,而不是分析规则:function
可以在另一个翻译单元中定义,因此编译器不一定知道引用将如何使用。它不能只是将值的拷贝发送给函数,并希望函数定义不会以需要定义引用对象的方式使用对象。同样,在编译函数时,编译器不能假定所有函数调用都会发送除对存在的对象的引用之外的任何内容。
从技术上讲,我想内联函数的引用参数可能还有更复杂的异常,但标准中没有这样的异常。而且不应该有,因为在这些情况下它会使内联扩展成为强制性的。在实践中,如果编译器恰好内联扩展函数,编译器可能会完全按照此类异常的要求运行,因为 odr 违规具有未定义的行为。
关于c++ - 出现在函数表达式中的变量是否通过引用获取参数但通过值 odr-used 返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45436736/