gpt4 book ai didi

c++ - C++ 不是强制要求 (cond ? string_1 : string_2) initialize a string?

转载 作者:行者123 更新时间:2023-12-01 13:30:14 24 4
gpt4 key购买 nike

考虑:

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

[expr.type/1]: If an expression initially has the type “reference to T ([dcl.ref], [dcl.init.ref]), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression. [..]


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

[expr.cond/5]: If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category and it is a bit-field if the second or the third operand is a bit-field, or if both are bit-fields.


和:

[expr.cond/7.1]: The second and third operands have the same type; the result is of that type and the result object is initialized using the selected operand.


初始化 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::stringconst std::string 初始化
  • 作为初始化对象的表达式,具有值类别右值(我相信这意味着该对象也是临时对象?)
  • 那么我们从那个临时初始化函数的返回值;这是邪恶的,因为返回类型是一个引用,所以我们悬空。
  • 最佳答案

    从您引用的那部分开始:

    If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category and it is a bit-field if the second or the third operand is a bit-field, or if both are bit-fields.


    第二个和第三个操作数都是 std::string const 类型的左值,所以结果是类型为 std::string const 的左值.

    Initialising a std::string from a std::string involves a copy.


    但是我们没有初始化 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/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com