考虑:

void foo(std::string& s);
在此函数内部,表达式s是左值std::string(不是std::string&),因为引用在表达式中并不真正“存在”:

现在考虑:
const std::string& foo(const std::string& s1, const std::string& s2)
{
    return (s1.size() < s2.size() ? s1 : s2);
}
另一个问题是关于条件运算符是否在这里涉及到一个临时变量的争论(该临时变量随后会影响作为悬挂引用的foo的返回值)。
我的解释是,是的,它必须是因为:

和:

std::string初始化std::string涉及一个拷贝。
但是,令我惊讶的是,海湾合作委员会(GCC)没有对悬挂的引用文件提出警告。经调查,我发现foo确实确实传播了所选参数的引用语义:
#include <string>
#include <iostream>

using std::string;
using std::cout;

void foo(string& s1, string& s2)
{
    auto& s3 = (s1.size() < s2.size() ? s1 : s2);
    s3 = "what";
}

int main()
{
    string s1 = "hello";
    string s2 = "world";

    foo(s1, s2);

    cout << s1 << ' ' << s2 << '\n';   // Output: hello what
}

(live demo)
通过引用传递给s2的原始foo已由条件运算符选择,然后绑定(bind)到s3并进行了修改。没有任何复制正在进行的证据。
这与我对表达式如何工作以及条件运算符如何工作的理解不符。
那么,我上面的哪些陈述是不正确的,为什么?

由于似乎有些困惑,因此在下面我示意了我的理解是事件链。我意识到这是错误的-以上我的测试案例证明了这一点。但我想确切地了解原因。理想情况下,我希望使用一些标准的措词,而不仅仅是“您错了”。我已经知道我错了。那就是我问的原因。 😀
  • 引用传递给函数
  • 的字符串
  • 评估的表达式包含条件运算符
  • 后两个操作数是const std::string类型的左值表达式(不是引用!)
  • 后两个操作数具有相同的类型和值类别,因此条件运算符的结果也是const std::string

  • 表达式的结果是从所选操作数初始化的;我们已经确定操作数和结果类型是const std::string,所以它是从const std::string
  • 初始化的const std::string
  • 作为初始化对象的表达式,其值类别为rvalue(我相信这意味着该对象也是临时的?)
  • 然后我们从那个临时变量初始化函数的返回值。这是邪恶的,因为返回类型是引用,所以我们悬而未决。
  • 最佳答案

    在本节中,您引用:

    第二和第三操作数都是std::string const类型的左值,因此结果是std::string const类型的左值。

    但是我们不是从std::string初始化std::string。在:

    const std::string& foo(const std::string& s1, const std::string& s2)
    {
        return (s1.size() < s2.size() ? s1 : s2);
    }
    
    我们正在从std::string const&类型的左值初始化std::string const。那仅仅是直接引用绑定(bind)。无需复制。

    关于c++ - C++是否不要求这样做(cond?string_1 : string_2) initialize a string?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63198098/

    10-12 22:34