C++中String()构造函数是左值还是右值?代码输出疑惑求解
问题与解答:右值引用与成员函数重载匹配
代码定义
String类定义
class String { public: String() { } ... void test() && { std::cerr << "right version" << std::endl; } void test() & { std::cerr << "left version" << std::endl; } void test_ctor(String &&s) { std::cerr << "right version" << std::endl; } void test_ctor(const String &s) { std::cerr << "left version" << std::endl; } ... private: ... };
main.cpp代码
int main() { String().test(); String lhs; lhs.test(); ([]() -> String { return String(); })().test(); lhs.test_ctor(lhs); lhs.test_ctor(String()); }
运行输出
right version left version right version left version left version
对应代码行的输出注释:
String().test(); // right version String lhs; lhs.test(); // left version ([]() -> String { return String(); })().test(); // right version lhs.test_ctor(lhs); // left version lhs.test_ctor(String()); // left version
核心疑问
String()调用test()时匹配右值版本,但作为test_ctor的参数时却匹配const String&版本,输出left version,原因是什么?String()是左值还是右值?
解答
String()是右值:直接调用构造函数创建的临时对象属于纯右值(prvalue),是右值的一种。成员函数重载匹配规则(
test()的情况):
C++11及以后支持引用限定符(&和&&)来重载成员函数:void test() &:仅能被左值对象调用,&限定符表示函数仅对左值实例可用。void test() &&:仅能被右值对象调用,&&限定符表示函数仅对右值实例可用。
所以String().test()中,临时对象是右值,匹配test() &&版本;lhs.test()中lhs是左值,匹配test() &版本。
函数参数匹配规则(
test_ctor的情况):
核心原因是test_ctor(String &&s)是非const的右值引用参数,而当临时对象无法被绑定到该参数时,编译器会退而选择const String&版本:const String&是兼容性极强的参数类型,可以绑定左值、右值、临时对象等所有类型的String表达式。- 如果你的类中存在阻止移动语义生效的情况(比如显式声明了拷贝构造函数但未声明移动构造函数,导致编译器不生成默认移动构造;或是移动构造函数被设为private),临时对象无法被绑定到非const的右值引用,编译器就会优先匹配
const String&版本。
内容的提问来源于stack exchange,提问作者Wiosier
相关产品推荐
相关产品推荐

