C++20中带引用参数的函数无法接受临时对象的问题咨询
C++20下临时对象绑定非const引用的解决方案
问题场景
升级到Visual Studio 2022并启用C++20标准后,以下原本正常运行的代码出现编译错误:
inline string& rtirm(string& s) { s.erase(s.find_last_not_of(' ') + 1); return s; } const char* buf = " abc "; string s_trim = rtirm(string(buf));
编译错误信息:
Error C2664 'std::string &rtirm(std::string &)': cannot convert argument 1 from 'std::string' to 'std::string &'
你已明确原因是非const左值引用无法绑定临时对象,但不想通过提前定义临时变量(如下代码)的方式增加代码复杂度:
string temp{buf}; string s_trim = rtirm(temp);
解决方案
不需要提前定义临时变量,有两种更简洁的处理方式:
方案1:添加右值引用重载
为函数增加一个接收右值引用的重载版本,同时保留原有的左值引用版本,既能处理普通左值,也能直接接收临时对象:
// 处理左值对象 inline string& rtirm(string& s) { s.erase(s.find_last_not_of(' ') + 1); return s; } // 处理临时右值对象 inline string&& rtirm(string&& s) { s.erase(s.find_last_not_of(' ') + 1); return std::move(s); }
修改后原调用代码无需改动,两种场景都能正常编译运行。
方案2:改为传值并返回新对象
直接让函数接收string值(而非引用),修改后返回处理后的字符串。这种方式更符合现代C++设计风格,避免引用相关问题,代码也更简洁:
inline string rtirm(string s) { s.erase(s.find_last_not_of(' ') + 1); return s; }
该方案下,无论传入左值还是临时右值都能正常工作,原调用代码保持不变即可。
补充说明
C标准从始至终都不允许非const左值引用绑定临时对象,旧版本Visual Studio之所以能运行是因为编译器放宽了标准限制。升级到C20后,VS严格遵循标准,因此触发了编译错误。
内容的提问来源于stack exchange,提问作者Zhang
相关产品推荐
相关产品推荐

