Clang中右值引用的异常行为:哪类编译器输出符合C++标准?
哪种编译器输出符合C++标准?
先看这段C++代码:
#include <iostream> struct A { A() { std::cout << "()" << std::endl; } A(A&&) { std::cout << "(A&&)" << std::endl; } A(const A&) { std::cout << "(const A&)" << std::endl; } }; A fun (A&& a){ return a; } int main(){ A a; fun(std::move(a)); return 0; }
不同编译器的输出表现
- Clang 16.0.3(arm64-apple-darwin22.4.0,采用C++17标准)下的输出:
() (A&&)
- 多数其他编译器(如GCC、MSVC)的输出:
() (const A&)
标准符合性分析
核心问题在fun函数的return a语句:
a是命名的右值引用参数,但它本身属于左值——C++标准明确规定,所有命名的变量(包括引用类型参数)都是左值,无论它绑定的是左值还是右值。- 当返回左值
a时,非const的右值引用(A&&)无法绑定到左值,因此编译器只能匹配拷贝构造函数(const A&),也就是多数编译器输出的结果。
Clang输出移动构造是因为它启用了一个非标准扩展:允许将返回语句中的命名右值引用参数视为右值触发移动构造,但这个行为并不符合C++标准要求。
结论:多数其他编译器的输出符合C++标准,Clang的输出是其自身扩展带来的非标准行为。
内容的提问来源于stack exchange,提问作者Kozmar
相关产品推荐
相关产品推荐

