在 C++ 三元运算符中使用字符串常量是对非左值数组的无效使用吗?

Posted

技术标签:

【中文标题】在 C++ 三元运算符中使用字符串常量是对非左值数组的无效使用吗?【英文标题】:Is using a string constant in C++ ternary operator an invalid use of non-lvalue array? 【发布时间】:2019-06-30 23:22:59 【问题描述】:

我的代码使用三元运算符检查条件,然后返回指向 c 字符串常量的指针或引发异常。

奇怪的是,只有当我从三元运算符的一个路径throw 时,编译才会失败。如果我在两边都放一个字符串常量,一切都会编译。

// this line gives no compilation error
auto str = condition ? "foo" : "bar";

// this line gives "error: invalid use of non-lvalue array"
auto str = condition ? "foo" : throw std::runtime_error"bad";

这个问题在 gcc 9.1 中开始出现。我多年来一直使用上述两种模式的行,它们在 clang 和早期版本的 gcc 中编译时没有警告。

上述模式实际上是无效的,还是 gcc 9.1 中的编译器错误?

【问题讨论】:

我认为很明显使用字符串文字不是问题,但抛出异常是。所以这个问题的答案是否定的,但实际的问题是在三元的一个分支中抛出异常是否合法。 @Slava 的问题是字符串文字是doesn't work,但是ints、it does。不过,我怀疑存在编译器错误,因为我同意问题可能在于条件运算符本身的throwing。 @Fureeish 我明白了,但是当有 2 个字符串文字时,它的工作原理与 OP 显示的一样好,所以问题仍然不是字符串文字本身,而是它与抛出异常的组合。所以主题是误导恕我直言。 "foo" 的类型是const char[4],编译器显然将其用作str 的类型,然后想将值从一个数组复制到另一个数组。我(还)不知道这是一个错误,还是语言变化(或语言解释)的原因,但作为一种解决方法,您可以将"foo" 转换为const char *(const char *) "foo". 有趣的是,cppreference.com 几乎使用了我遇到问题的确切行作为示例 (en.cppreference.com/w/cpp/language/operator_other)。 【参考方案1】:

你是对的。如果另一个操作数是 throw 表达式,则三元运算符传播一个操作数的类型和值类别。条件表达式是const char[4] 类型的左值。 auto 然后推导出 const char*。这里没有“无效使用非左值数组”。

此外,代码使用 clang 编译 fine。我会说这是 GCC 的一个错误。

【讨论】:

感谢您的确认。我将其作为 GCC 开发人员的错误提出。

以上是关于在 C++ 三元运算符中使用字符串常量是对非左值数组的无效使用吗?的主要内容,如果未能解决你的问题,请参考以下文章

三元运算符为啥以及何时返回左值?

即使在三元运算符中给出的左值很好,赋值语句也会出错

三目运算符

编译器开发系列--Ocelot语言5.表达式的有效性检查

表达式和语句

左值的 C++ std::move() 性能明智