【问题标题】:How can I declare and define multiple variables in one line using C++?如何使用 C++ 在一行中声明和定义多个变量?
【发布时间】:2011-10-13 21:11:29
【问题描述】:

我一直认为,如果我声明这三个变量,它们的值都会为 0

int column, row, index = 0;

但我发现只有索引等于 0,其他都是垃圾,例如 844553 和 2423445。

如何在不将每个变量都声明为新行的情况下将所有这些变量初始化为零?

【问题讨论】:

  • 小心那些单行多变量声明。声明一个 int 指针后跟一个常规整数列表比您想象的要容易(int* a, b, c; 不像它看起来那样)。
  • 只有三个变量,伙计,在定义中为每个变量写上=0。而且,如果你真的想要很多变量,那么试试一个数组:int a[10]={0} 将为你将每个 a[i] 初始化为 0。
  • 编译器不应该允许这种结构,如果它的行为不同于一个合理的程序员所期望的......恕我直言
  • @cph2117 一个理性的程序员会认为'嗯,这个语法可能意味着几个不同的东西,这取决于语法如何绑定东西',查看标准以找出答案这是真的,继续努力。
  • 停止这样做。它只会使代码更难阅读。用高级语言编写代码的目的是让维护者更容易阅读。

标签: c++


【解决方案1】:

从 C++17 开始,您可以使用 Structured Bindings:

#include <iostream>
#include <tuple>

int main () 
{
    auto [hello, world] = std::make_tuple("Hello ", "world!");
    std::cout << hello << world << std::endl;
    return 0;
}

Demo

【讨论】:

    【解决方案2】:

    正如其他人所提到的,从 C++17 开始,您可以使用 structured bindings 进行多个变量赋值。

    将其与std::arraytemplate argument deduction 结合使用,我们可以编写一个函数,为任意数量的变量赋值而无需重复类型或值

    #include <iostream>
    #include <array>
    
    template <int N, typename T> auto assign(T value)
    {
        std::array<T, N> out;
        out.fill(value);
        return out;
    }
    
    int main()
    {
        auto [a, b, c] = assign<3>(1);
    
        for (const auto& v : {a, b, c})
        {
            std::cout << v << std::endl;
        }
    
        return 0;
    }
    

    Demo

    【讨论】:

      【解决方案3】:

      我不建议这样做,但如果你真的喜欢它是一行并且只写一次 0,你也可以这样做:

      int row, column, index = row = column = 0;
      

      【讨论】:

        【解决方案4】:

        当您声明一个变量而不对其进行初始化时,会从内存中选择一个随机数并将该变量初始化为该值。

        【讨论】:

        • 并非如此。编译器决定“这个变量将位于地址 xxx”,无论发生在地址 xxx 的什么都将是初始值,除非它明确地设置为某些东西(通过初始化或赋值)
        • @pm100 虽然 更好,对于任何不会骚扰用户的琐碎实现都是如此......这仍然过于简单化 ;-) 使用未初始化的变量是 UB,因此理论上任何事情都可能发生,包括任何使用该变量的代码都被简单地从程序中剥离出来 - 这在优化过程中尤其可能发生。
        • 该变量的值将是它获得的地址中的任何内容,即垃圾。
        • @PedroVernetti 在声明新变量并碰巧获得相同地址之前,在所述地址发生了什么并不重要。如果用户声明新变量而没有用值初始化它,然后在为其赋值之前读取该变量,则程序具有未定义的行为。这比“随机”和“垃圾”要糟糕得多,需要避免。
        【解决方案5】:

        如果每行声明一个变量/对象,不仅可以解决这个问题,而且可以使代码更清晰,并防止在声明指针时出现愚蠢的错误。

        不过,要直接回答您的问题,您必须将每个变量显式初始化为 0。 int a = 0, b = 0, c = 0;.

        【讨论】:

          【解决方案6】:

          可能的方法:

          • 用零初始化所有局部变量。
          • 有一个数组,memset{0} 数组。
          • 使其成为全局或静态的。
          • 将它们放在structmemset 中,或者有一个可以初始化的构造函数 他们归零。

          【讨论】:

          • #define COLUMN 0 #define ROW 1 #define INDEX 2 #define AR_SIZE 3 int Data[AR_SIZE]; // 只是一个想法。
          • 抱歉,我的意思是,您为什么在回答中包含“有一个数组、memset 或{0}数组。”这行?
          • memset(Data, 0, sizeof(Data)); // 如果这可以被逻辑打包。
          【解决方案7】:

          当您声明时:

          int column, row, index = 0;
          

          只有索引设置为零。

          但是您可以执行以下操作:

          int column, row, index;
          column = index = row = 0;
          

          但我个人更喜欢已经指出的以下内容。
          在我看来,这是一种更易读的形式。

          int column = 0, row = 0, index = 0;
          

          int column = 0;
          int row = 0;
          int index = 0;
          

          【讨论】:

          • 在最后两个之间,我根据这两个值是否真的必须是同一类型 (bool previousInputValue, presentInputValue;) 或者它们现在恰好是同一类型但实际上不需要是相同的类型来决定(uint8_t height, width; 将来可能会变成uint8_t height; uint16_t width;,应该是uint8_t height; uint8_t width;)。
          • 因为写uint8_t height; uint16_t width;而不是uint8_t height, width;以后可以节省10个字符。 :-) 你当然可以随心所欲。只要确保它易于阅读。所以最后一种形式是最明确的。
          • 最后一种形式无疑是最明确地说明每个变量的类型并清楚地表明每个变量都已初始化。也就是说,列和行是否应该是相同的类型并没有明确说明。也许我们都更喜欢int presentValue = 0; typeof(presentValue) previousValue = presentValue; 的明确性,但我相信typeof() 是一个非标准的GCC 扩展。
          【解决方案8】:

          正如@Josh 所说,正确答案是:

          int column = 0,
              row = 0,
              index = 0;
          

          您需要注意与指针相同的事情。这个:

          int* a, b, c;
          

          相当于:

          int *a;
          int b;
          int c;
          

          【讨论】:

          • 我讨厌那个指针的东西,它没有任何意义。星号是类型的一部分,因此它应该适用于所有类型。想象一下,如果 unsigned long x, y;x 声明为 unsigned longy 声明为 unsigned,又名 unsigned int!那是完全一样的!
          • 有道理。 "int *a, b, c;"
          • @JeroenBollen 好吧,如果你在变量名而不是类型旁边写上你的指针星号是有意义的,但这本身没有任何意义。就像我上面说的,星号是类型的一部分,而不是名称的一部分,所以它应该与类型分组!
          • 另一方面,实际上 * 不一定是类型的一部分是有道理的,因为 int *a 意味着 *a 代表 int 值。
          • 这一点已经提出,但只是添加到它 void 本质上是缺少类型,但您仍然可以指向它。因此为什么void* a 会编译而void *a, b, c 不会。这种合理化对我有用。
          【解决方案9】:
          int column(0), row(0), index(0);
          

          请注意,此表单也适用于自定义类型,尤其是当它们的构造函数采用多个参数时。

          【讨论】:

          • 现在采用统一初始化(等待 C++17 为 auto... 修复此问题): int column { 0 } ,行 { 0 } ,索引 { 0 } ;
          【解决方案10】:
          int column = 0, row = 0, index = 0;
          

          【讨论】:

          • 嗨,我想知道这个表达式是否支持所有类型,如 std::vector 等或仅支持主要数据类型
          猜你喜欢
          • 1970-01-01
          • 2014-09-17
          • 1970-01-01
          • 2011-06-18
          • 1970-01-01
          • 2017-09-20
          • 2022-11-25
          • 2011-04-30
          • 2020-12-13
          相关资源
          最近更新 更多