是否可以用 if 声明自动变量?

Is it possible to declare auto variables with an if?

我的代码在下面。

struct conv{
    struct des
    {
        des(int a) {}
        des(int a, int b) {}
        des(int a, int b, int c) {}
    };
};
int main(int argc, const char * argv[]) {

int a = 1;
int b = 1;
int c = 1;

if (a > 1)
{
    auto conv_desc = conv::des(1, 2, 3);
} else if(b > 1) {
    auto conv_desc = conv::des(1, 2);
} else {
    auto conv_desc = conv::des(1);
}
    return 0;
}

代码的模式是从 mkldnn 中提取的。我唯一想做的就是从 if-else 语句中取出 auto conv_desc 。 我试图在 if-else 语句中声明 auto conv_desc 。 它发生了一个错误: 宣言

variable 'conv_desc' with deduced type 'auto' requires an initializer

或者如果我像下面这样使用指针,我得到一个空指针。

另一种方式出错:

Taking the address of a temporary object of type 'conv::des'

如果我不能解决这个问题,我将不得不在每个分支中写一大段重复的代码。

不要使用自动。如果需要声明一个变量,还不能赋值,那就不能用auto了。

int main(int argc, const char * argv[]) {
    // ...
    conv::des conv_desc; // calls default constructor.

    if (a > 1)
    {
        conv_desc = conv::des(1, 2, 3);
    } else if(b > 1) {
        conv_desc = conv::des(1, 2);
    } else {
        conv_desc = conv::des(1);
    }
    // conv_desc is initialized at this point.
    return 0;
}

你不能像这样使用指针

int *a;
{ // new scope
    int b = 5;
    a = &b; // error.
}
// b is no longer in scope here

b 超出范围时,a 将指向 b 曾经所在的地址,现在不再有效。

如果你想使用指针那么你可以使用new。然而在那种情况下你必须之后释放内存。

int main(int argc, const char** argv)
{
    conv::des *conv_desc = nullptr; // does not call default constructor.

    if (a > 1)
    {
        conv_desc = new conv::des(1, 2, 3);
    } else if(b > 1) {
        conv_desc = new conv::des(1, 2);
    } else {
        conv_desc = new conv::des(1);
    }
    if (conv_desc == nullptr) { /* memory allocation failed */ }
    // conv_desc is initialized at this point.
    // ...
    // remember to delete conv_desc
    if (conv_desc != nullptr) { delete conv_desc; conv_desc = nullptr; }
    return 0;
}

将您的 if 代码移动到单独的函数中:

conv::des make_des(int a, int b) {
  if (a > 1) {
    return conv::des(1, 2, 3);
  } else if(b > 1) {
    return conv::des(1, 2);
  } else {
    return conv::des(1);
  }
}

int main(int argc, const char * argv[]) {
  int a = 1;
  int b = 1;
  int c = 1;
  auto conv_desc = make_des(a, b);
  return 0;
}

如果将 if ... else 链移动到单独的函数中,则可以使用 return

struct conv
{
    struct des
    {
        des(int a) {
        }

        des(int a, int b) {
        }

        des(int a, int b, int c) {
        }
    };
};

conv::des make_conv_des(int a, int b)
{
    if (a > 1) {
        return conv::des(1, 2, 3);
    } else if(b > 1) {
        return conv::des(1, 2);
    } else {
        return conv::des(1);
    }
}

int main(int argc, const char * argv[]) {

    int a = 1;
    int b = 1;

    auto conv_des = make_conv_des(a, b);

    return 0;
}

您也可以使用立即调用的 lambda。这是一种常见的模式,可以在其他情况下将某些变量设为 const。

此解决方案与@yachoor 的答案非常相似,但使用了 lambda。

int main(int argc, const char * argv[]) {
    int a = 1;
    int b = 1;
    int c = 1;

    // Kind of an inline function that is called immediately
    auto const conv_desc = [&]{
        if (a > 1) {
            return conv::des(1, 2, 3);
        } else if(b > 1) {
            return conv::des(1, 2);
        } else {
            return conv::des(1);
        }
    }();
    // Parens calls the function

    return 0;
}

您似乎让代码过于复杂了。不清楚为什么要以这种方式区分这三个构造函数。为什么不使用这样的默认值来隐藏对象内部的复杂性?

struct conv{
    struct des
    {
        des(int a, int b = 0, int c = 0) {
          if(a > 1) {
            /// do some logic
          } else if(b > 1) {
            // do some logic
          } else {
            // do some logic
          }

        }
    };
};
int main(int argc, const char * argv[]) {

  int a = 1;
  int b = 1;
  int c = 1;

  auto conv_desc = conv::des(a, b, c);

  return 0;
}