【问题标题】:With C++20, function with reference argument doesn't accept a tempoary object [duplicate]使用 C++20,具有引用参数的函数不接受临时对象 [重复]
【发布时间】:2023-02-22 18:54:17
【问题描述】:
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));

在我将 visual studio 升级到 2022 并使用 C++20 之前,这段代码一直运行良好。

错误 C2664 'std::string &rtirm(std::string &)': 无法转换 从 'std::string' 到 'std::string &' 的参数 1

我很清楚原因——引用不能引用临时对象。 但这使代码更加复杂。我必须在调用 trim 之前定义一个变量吗?

string temp{buf};
string s_trim = rtirm(temp);

【问题讨论】:

  • 顺便说一句,这与 C++20 标准的变化无关,而是默认情况下较新的编译器更严格。请参阅 /permissive 选项。
  • iirc msvc 允许在某些情况下将临时对象绑定到非常量引用作为非标准扩展,但我不知道任何细节,也没有解释为什么它停止工作。尽管无论如何应该修复代码
  • godbolt.org/z/z9PTbbM55 所以现在 MSVC 的行为与其他编译器一样。注意 warring 已归档,因此如果您将警告视为错误,则在旧版本中它将是相同的。

标签: c++ visual-c++ c++20


【解决方案1】:
inline string& rtirm(string& s)
{
    s.erase(s.find_last_not_of(' ') + 1);
    return s;
}

inline string rtrim(string&& s)
{
    s.erase(s.find_last_not_of(' ') + 1);
    return s;
}

void test(){
    const char* buf = "    abc    ";
    string sTemp{ buf };
    rtrim(sTemp);
    
    string s_trim = rtrim(string(buf));
}

我更喜欢这个,添加一个右值引用版本,它使引用和右值引用参数都有效。

【讨论】:

  • 假设你做std::string& s = rtirm(string(buf));然后你回到原点。
【解决方案2】:

是的,您必须定义一个变量,然后使用它而不是临时对象调用 rtrim。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-01
    • 1970-01-01
    • 2022-07-21
    • 1970-01-01
    • 2013-08-29
    • 2011-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多