为什么不能在 do while 循环的表达式部分内声明一个变量?
Why can't you declare a variable inside the expression portion of a do while loop?
以下语法有效:
while (int i = get_data())
{
}
但以下不是:
do
{
} while (int i = get_data());
我们可以通过标准草案N4140
6.4节了解原因:
1 [...]
条件: 表达属性-说明符-seqoptdecl-specifier-seq declarator = initializer-clauseattribute-specifier-seqoptdecl-specifier-seq declarator braced-init-list2 条件规则既适用于选择语句,也适用于 到
for
和while
声明(6.5(。[...]
和第 6.5 节
1 迭代语句指定循环。
迭代语句:while
(条件(语句do
语句while
(表达式( ;
相反,你被迫做一些丑陋的事情,比如:
int i = get_data();
do
{
} while ((i = get_data())); // double parentheses sic
这样做的理由是什么?
将是问题所在,在do while
语句的while
部分中声明i
的范围是什么?当声明实际上位于循环本身下方时,在循环中有一个可用的变量似乎很不自然。其他循环没有此问题,因为声明位于循环主体之前。
如果我们看一下草案C++标准部分[stmt.while]p2,我们会看到while语句:
while (T t = x) statement
相当于:
label:
{ // start of condition scope
T t = x;
if (t) {
statement
goto label;
}
} // end of condition scope
和:
在条件中创建的变量将在循环的每次迭代中销毁和创建。
我们如何为do while
案制定这一点?
正如Cdhowie指出的那样,如果我们看一下第[stmt.do]p2节,它说(强调我的(:
在 do 语句中,重复执行子语句,直到 表达式的值变为假。测试在每次之后进行 语句的执行。
这意味着在我们到达声明之前就对循环的主体进行了评估。
虽然我们可以为这种情况创建一个例外,但它会违反我们的直觉,即一般来说,名称的声明点是在我们看到完整的声明(例如类成员变量有一些例外(之后,但好处不明确。声明点在第 3.3.2
节中介绍。
原因可以解释为什么很难允许。
该语言坚持一般规则,即所有内容都应在使用点之上声明。在这种情况下,do-while
中声明的变量将声明在其预期自然范围(循环体(以下。要在循环内访问此变量,则需要对do-while
个循环进行特殊处理。尽管我们知道这种特殊处理的例子(例如,类内成员函数体可以看到所有类成员,包括下面声明的成员(,但在do-while
周期中这样做可能没有多少实际意义。
在do-while
的情况下,这些特殊处理规则还需要找到一种有意义的方法来处理以这种方式声明的变量的初始化。请注意,在C++语言中,此类变量的生存期仅限于循环的一次迭代,即在每次迭代时创建和销毁变量。这意味着对于do-while
循环,变量将始终保持未初始化状态,除非您引入一些规则以某种方式将初始化移动到循环体的开头。在我看来,这将是相当令人困惑的。
块之后声明i
然后能够在块中访问它是非常不自然的。for
和 while
中的声明是很好的简写,它们对循环逻辑中所需的变量进行有限范围的使用。
这样做更干净:
int i;
do {
i = get_data();
// whatever you want to do with i;
} while (i != 0);
这是因为其他所有内容都遵循在使用变量之前声明变量的做法,例如:
public static void main(String[] args){
// scope of args
}
for(int i=1; i<10; i++){
// scope of i
}
{
...
int somevar;
//begin scope of var
...
//end of scope of var
}
这是因为事情是自上而下解析的,并且因为遵循这个约定可以保持直观,因此为什么你可以声明一个 while(int var <10(,因为该 var 的范围将是声明之后循环内的区域。
do while 声明变量没有任何意义,因为范围将在检查的同时结束,因为那是该块完成的时候。
添加这个
#define do(cond) switch (cond) do default:
在代码的开头。
现在,你可以写
do (int i = get_data())
{
// your code
} while ((i = get_data()));
重要的是,此#define
不会破坏 do-while 循环中 do
关键字的原始语法。
但是,我承认这是晦涩难懂的。
您的第一个语法有效,而第二个语法无效。但是,您的 while 循环将永远循环,即使您的函数 get_data(( 返回 0。不确定这是否正是您想要发生的事情。
- 在疯狂的部分中声明变量
- 如何在C++中为高分辨率时钟声明变量?
- 在命名空间中声明变量,在 main 中定义它,使其对所有其他文件可见
- CUDA 的性能取决于声明变量
- 如何在不为其声明变量的情况下获取和使用常量值的地址?
- C++声明变量时自动类型推断而不初始化
- 在不同循环中多次声明变量的优点
- 奇怪的错误 C2131 与 constexpr 声明变量
- 是否可以在 "if" 语句中声明变量?
- 在python-ctypes中声明变量并传递给dll函数
- 在递归函数C++中声明变量
- 只有一个定义/声明时标头声明变量的多堆定义错误
- 奇怪的未声明变量编译器错误
- 我在C++程序中声明变量时遇到问题
- 在命名空间中声明变量
- C++ lambda 按值捕获,而无需更早声明变量
- 声明变量以保存字符串列表时的内存分配
- 如何声明C 变量应突变
- 为什么允许在开关语句中声明变量?但不是声明 初始化
- 在同一命名空间中声明变量和函数是否出错?[C++]