为什么检查分配操作的结果有效,但不能与其他条件相结合

Why does checking the result of an assignment operation work, but cant be combined with other conditions?

本文关键字:但不能 其他 条件 相结合 有效 分配 检查 操作 结果 为什么      更新时间:2023-10-16

我知道赋值运算符返回实际赋值,以便使类似的操作

int a = b = c = 5;

因此,扩展这个概念,这就是为什么可以(思想使调试变得困难(编写这个代码

class A {
public:
  A();
  ~A();
};
int main(int argc, char** argv) {
  if (A* checkedA = new A()) {
    //this works just fine
  }
}

但是,我的问题是,为什么不能将赋值运算符的结果与任何其他检查相结合

  if (true && A* checkedA2 = new A()) {
    //this doesn't compile
  }
  if (true && (A* checkedA3 = new A())) {
    //parenthesis won't help
  }
  if (A* checkedA4 = new A() && A* checkedA5 = new A()) {
    //this will also fail
  }

在我的mac上的叮当++上我得到:

➜  Desktop  clang++ -c assign.cc
assign.cc:14:15: error: 'A' does not refer to a value
  if (true && A* checkedA2 = new A()) {
              ^
assign.cc:1:7: note: declared here
class A {
      ^
assign.cc:14:18: error: use of undeclared identifier 'checkedA2'
  if (true && A* checkedA2 = new A()) {
                 ^
assign.cc:18:19: error: expected ')'
  if (true && (A* checkedA3 = new A())) {
                  ^
assign.cc:18:15: note: to match this '('
  if (true && (A* checkedA3 = new A())) {
              ^
assign.cc:18:39: error: expected expression
  if (true && (A* checkedA3 = new A())) {
                                      ^
assign.cc:22:33: error: 'A' does not refer to a value
  if (A* checkedA4 = new A() && A* checkedA5 = new A()) {
                                ^
assign.cc:1:7: note: declared here
class A {
      ^
assign.cc:22:36: error: use of undeclared identifier 'checkedA5'; did you mean 'checkedA4'?
  if (A* checkedA4 = new A() && A* checkedA5 = new A()) {
                                   ^~~~~~~~~
                                   checkedA4
assign.cc:22:10: note: 'checkedA4' declared here
  if (A* checkedA4 = new A() && A* checkedA5 = new A()) {
         ^
6 errors generated.

我在Visual Studio中也遇到了类似的错误,所以我认为这可能不是编译器一致性的问题,而是标准问题?

那为什么呢?背后的原因是什么?我知道这会让代码的阅读(甚至解析(变得有点困难,但为什么连括号都不能解决这个问题呢?

首先考虑:

A* checkedA;
if (checkedA = new A()) { ... }

这里有一个赋值,赋值返回被赋值的值,这就是为什么我们可以使用赋值作为if语句的条件。然而,在中

if (A* checkedA = new A()) { ... }

没有发生转让;相反,您得到的是变量checkedA声明,然后用new A()对其进行初始化。等号表示复制初始化,而不是赋值。

因此,这之所以有效,并不是因为赋值返回了赋值;事实上,我们这里有一个特殊情况,它允许您在ifforwhileswitch语句的条件内进行声明。但只有当声明是整个条件时才允许;这就是为什么像if (true && A* checkedA2 = new A())这样的东西不起作用的原因。

在这种特殊情况下,声明的变量的值被转换为bool,并用作条件。在该语言的其他地方,声明不具有值,并且不能将视为表达式。

if (A* checkedA = new A()) {
    //this works just fine
}

此处的条件未使用赋值运算符。它实际上是一个带有初始化程序的变量声明。该标准有一个特殊的子句,规定如果选择语句(ifswitch(的条件是一个声明,则条件的值就是该声明初始化时使用的值。

true && A* checkedA2 = new A()

问题是它不是一个有效的表达式。不能在表达式中嵌套声明。但是,您可以在if语句之前声明checkedA,然后在条件中使用赋值:

A* checkedA2;
if (true && (checkedA2 = new A())) {
  // ...
}
相关文章: