如何使用C ++在一行中声明和定义多个变量?


172

我总是说,如果我声明这三个变量,它们的值都将为0

int column, row, index = 0;

但是我发现只有索引等于零,其他索引就像844553和2423445一样是垃圾。

我如何将所有这些变量初始化为零,而无需在新行中声明每个变量?


36
小心那些单行的多变量声明。声明一个int指针,后面跟一个规则的整数列表,这比您想象的要容易得多(int* a, b, c;实际上不做任何事情)。
克里斯·埃伯勒

4
定义中只有三个变量dude =0为每个变量写。而且,如果您确实想要很多变量,请尝试一个数组:int a[10]={0}将为您初始化每个变量a[i]为0。
Stan

如果编译器的行为与合理的程序员期望的不同,则编译器不应允许该编译器... imho
cph2117

1
@ cph2117一个合理的程序员会想:“嗯,这种语法可能意味着几件不同的事情,具体取决于语法如何绑定事物”,查找标准以找出正确的事物,然后继续进行下去。
underscore_d

别这样 这只会使代码更难阅读。用高级语言编写代码的目的是使维护人员易于阅读。
马丁·约克

Answers:



161

当您声明:

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;

3
在最后两个值之间,我根据两个值是否必须确实是同一类型(bool previousInputValue, presentInputValue;)或现在是否恰好是相同类型但实际上并不需要,决定(将来uint8_t height, width;可能会变成uint8_t height; uint16_t width;并且应该是uint8_t height; uint8_t width;首先)。
altendky 2015年

因为将来写uint8_t height; uint16_t width;而不是uint8_t height, width;保存10个字符。:-)当然,您也可以随心所欲。只要确保您使其易于阅读即可。因此,最后一种形式是最明确的。
马特

最后一种形式无疑是最明确的形式,它说明了每个变量的类型并清楚地说明了每个变量都已初始化。也就是说,关于列和行是否应为相同类型尚不明确。也许我们俩都希望使用的明确性int presentValue = 0; typeof(presentValue) previousValue = presentValue;,但是我认为这typeof()是非标准的GCC扩展。
altendky

49

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

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

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

int* a, b, c;

等效于:

int *a;
int b;
int c;

34
我讨厌那个指针,没有任何意义。星号是该类型的一部分,因此它应适用于所有这些。试想一下,如果unsigned long x, y;申报xunsigned long,但y作为刚unsigned,又名unsigned int!那是完全一样的!</ rant>
Cam Jackson

6
这说得通。“ int * a,b,c;”
Jeroen 2013年

7
@JeroenBollen是的,如果将指针星号写在变量名旁边而不是类型旁边,这是有道理的,但这本身没有任何意义。就像我上面说的,星号是类型的一部分,而不是名称的一部分,因此应按类型分组!
凸轮杰克逊

11
从侧面看,实际上*不一定是类型的一部分,因为int *a*a表示int值。
mdenton8

2
已经指出了要点,但仅在其中添加void实际上就是缺少类型,但是您仍然可以指向它。因此为什么void* a会编译而void *a, b, c不会编译。这种合理化对我有用。
2015年

24

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

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


16
int column(0), row(0), index(0);

请注意,这种形式也适用于自定义类型,尤其是当其构造函数使用多个参数时。


2
如今具有统一的初始化(在C ++ 17中为auto...进行了修复):int列{ 0 },行{ 0 },索引{ 0 }
underscore_d

5

从2k18开始,您可以使用结构化绑定

#include <iostream>
#include <tuple>

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

Demo


4

可能的方法:

  • 用零初始化所有局部变量。
  • 有一个数组memset{0}数组。
  • 将其设为全局或静态。
  • 将它们放在中structmemset或具有将其初始化为零的构造函数。

#define COLUMN 0 #define ROW 1 #define INDEX 2 #define AR_SIZE 3 int Data [ AR_SIZE ]; //只是一个想法。
阿杰(Ajay)

抱歉,我的意思是,为什么在答案中包含“ 具有数组,内存集或{0}数组 ”行?
Mateen Ulhaq

memset(Data,0,sizeof(Data)); //如果可以逻辑打包。
阿贾伊

2

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

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

0

正如其他人提到的那样,从C ++ 17开始,您可以将结构化绑定用于多个变量分配。

将其与模板参数推导结合使用std::array,我们可以编写一个函数,该函数将值分配给任意数量的变量,而无需重复类型或值

#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


-13

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


7
并不是的。编译器决定“此变量将位于地址xxx”,除非在地址xxx处明确设置了某个值(通过初始化或赋值),否则它将是初始值
pm100

3
@ pm100虽然更好,但对于任何不会干扰用户的琐碎实现都是正确的……这仍然过于简化;-)因为使用未初始化的变量是UB,所以理论上任何事情都可能发生,包括任何代码只需从程序中删除该变量即可-尤其是在进行优化时。
underscore_d

1
该变量的值将等于其到达的地址,即垃圾。
Pedro Vernetti

@PedroVernetti在声明新变量并碰巧获得相同地址之前,在所述地址发生了什么都没关系。如果用户在未使用值初始化的情况下声明了新变量,然后在为变量赋值之前先读取了该变量,则程序具有未定义的行为。这绝对比“随机”和“垃圾”更糟,只需要避免。
underscore_d
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.