c++ - 出现在函数表达式中的变量是否通过引用获取参数但通过值 odr-used 返回?

标签 c++ language-lawyer c++17

给定代码片段:

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 退出状态

ISO 标准 C++17 草案 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).

问:为什么这里需要定义变量varvar 不是表示出现在外部函数调用表达式的 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/

相关文章:

c++ - 在 C++ 中寻找 strtok() 的替代方案

c++ - 我可以只对那些 std::is_trivially_move_* 东西使用 memcpy 吗?

c++ - 局部常量变量不是 constexpr 可评估的,但无法弄清楚为什么

c++ - 解析模板类的专用静态成员变量的定义

c++ - 为什么在具有相同签名的模板和非模板函数之间进行选择时没有歧义?

c++ - 将指向基成员的指针转换为指向派生成员的指针

c++ - 如何为内联变量模板创建自定义点?

python - 输入到 C++ 可执行 python 子进程

c++ - 在类中初始化静态 POSIX 信号量

c++ - MPI_Gather 的段错误