常量求值期间是否允许Copy elision(如NRVO)?MSVC行为合规性探讨
常量表达式中复制消除的编译器行为疑问
在常量表达式和常量初始化中,从不执行复制消除。
但实际测试中存在例外情况:以下代码定义了constexpr函数f,它返回A类型对象res,同时接收同类型对象指针p作为参数。只有在**命名返回值优化(NRVO)**生效的场景(比如A res = f( &res )这类写法)下,才会出现&res == p为真的情况:
struct A { bool nrvo = false; }; constexpr A f( A * p = nullptr ) { A res = p ? A{ .nrvo = &res == p } : f( &res ); return res; } // 在MSVC中失败 static_assert( !f().nrvo );
按照标准预期,常量求值期间nrvo应该为false,但Visual Studio编译器会让这个断言失败。
这是MSVC的编译器实现错误。
根据C++标准,常量表达式求值过程中严格禁止复制消除(包括NRVO)——复制消除属于优化行为,而常量求值必须严格遵循标准语义,不能通过优化改变程序的可观测行为。MSVC错误地在常量求值流程中应用了NRVO,导致&res == p成立,违反了标准规定。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

