在C++中声明和初始化Conditional或Control语句中的变量

Dan*_*ham 26 c++ compiler-construction conditional declaration

在Stroustrup的The C++ Programming Language:Special Edition(3rd Ed)中,Stroustrup写道,控制语句条件中的变量声明和初始化不仅是允许的,而且是鼓励的.他写道,他鼓励它,因为它将变量的范围缩小到只有它们所需的范围.所以像这样......

if ((int i = read(socket)) < 0) {
    // handle error
}
else if (i > 0) {
    // handle input
}
else {
    return true;
}
Run Code Online (Sandbox Code Playgroud)

...是很好的编程风格和实践.该变量i仅存if在于需要它的语句块中,然后超出范围.

但是,g ++(版本4.3.3 Ubuntu特定编译)似乎不支持编程语言的这个特性,这对我来说是令人惊讶的.也许我只是用一个标志来调用g ++来关闭它(我称之为的标志是-g-Wall).在使用这些标志进行编译时,我的g ++版本返回以下编译错误:

socket.cpp:130: error: expected primary-expression before ‘int’
socket.cpp:130: error: expected `)' before ‘int’
Run Code Online (Sandbox Code Playgroud)

在进一步的研究中,我发现我似乎并不是唯一一个不支持此编译器的编译器.并且在这个问题中似乎存在一些混淆,因为确切地说语言在语言中是什么标准,以及编译器使用它编译什么.

所以问题是,什么编译器支持这个功能以及需要设置哪些标志才能编译?这是某个标准而不是其他标准的问题吗?

另外,出于好奇,人们普遍认同Stroustrup这是好风格吗?或者这是一种语言的创造者在他脑海中获得一个想法的情况,这个想法不一定得到语言社区的支持?

Red*_*yph 18

它被允许在嵌套块的控制部分来声明一个变量,但在的情况下ifwhile,变量必须初始化到将被解释为条件的数值或布尔值.它不能包含在更复杂的表达中!

在您展示的特定情况下,不幸的是您似乎无法找到遵守的方法.

我个人认为最好保持局部变量尽可能接近代码中的实际生命周期,即使从C切换到C++或从Pascal切换到C++时听起来很震撼 - 我们习惯于看到所有的变量一个地方.有了一些习惯,你会发现它更具可读性,你不必去其他地方寻找声明.而且,你知道在那之前没有使用它.


编辑:

话虽如此,我认为在一个声明中混合太多并不是一个好习惯,我认为这是一个共同的观点.如果影响变量的值,则在另一个表达式中使用它,通过分离两个部分,代码将更具可读性并且更少混淆.

所以不要使用这个:

int i;
if((i = read(socket)) < 0) {
    // handle error
}
else if(i > 0) {
    // handle input
}
else {
    return true;
}
Run Code Online (Sandbox Code Playgroud)

我更喜欢这样:

int i = read(socket);
if(i < 0) {
    // handle error
}
else if(i > 0) {
    // handle input
}
else {
    return true;
}
Run Code Online (Sandbox Code Playgroud)


EFr*_*aim 11

当与可能的NULL指针一起使用时,我认为它是一个好的样式:

if(CObj* p = GetOptionalValue()) {
   //Do something with p
}
Run Code Online (Sandbox Code Playgroud)

这种方式是否声明了p,它是一个有效的指针.没有悬空指针访问危险.

另一方面,至少在VC++中它是唯一受支持的(即检查赋值是否为真)


Bil*_*ill 6

在这些情况下我尽可能使用const.而不是你的例子,我会这样做:

const int readResult = read(socket);
if(readResult < 0) {
    // handle error
} 
else if(readResult > 0)
{
    // handle input
} 
else {
    return true;
} 
Run Code Online (Sandbox Code Playgroud)

因此,虽然范围不包含,但它并不重要,因为变量不能改变.


sp2*_*nny 5

他们正在c ++ 17中修复此问题:

if (int i = read(socket); i < 0)
Run Code Online (Sandbox Code Playgroud)

在哪里if可以有一个初始化语句。

参见http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html