在循环内定义变量是否很好?[关闭]


15

我的老师曾经告诉过我,我不应该在循环内定义变量,但是老实说,我仍然不明白为什么。

那有什么缺点?

有人能向我解释吗?


7
您的老师教什么编程语言?
布赖恩

2
如果在循环中使用非原始类型定义变量,则程序可能会在每次循环中最终不必要地调用其构造函数。如果只需要在循环外定义一次,则执行此操作。
布兰丁2015年

17
当您对讲师的发言感到困惑时,最好的资源就是请教官。它们可以为您提供Q&A站点无法提供的密集的来回交流。

1
跨站点重复:在循环之前或循环中声明变量之间的区别?(当然,该站点上有很多关于此类基本问题的重复项(包括仅与C ++有关的问题))。
彼得·莫滕森

2
该建议是针对特定环境的。就个人风格而言,我更喜欢声明我的变量,const除非有理由不这么做(函数编程的习惯)。要么我不会修改它们,优化器应该检测出何时不需要它们,或者我会并且已经避免了严重的错误。当这些常数中间值特定于循环的迭代时,这意味着在循环内声明它们。但是,还有一次需要在循环外声明变量的时候是在循环外引用变量。例如,您存储的结果。
戴维斯洛

Answers:


42

在循环中定义变量不是问题。实际上,这是一个好习惯,因为标识符应限制在最小范围内。

不好的是,如果您可以在循环运行分配一次变量,则可以在循环内分配变量。根据分配右侧的复杂程度,这可能会变得相当昂贵,甚至可能支配循环的运行时间。如果编写的循环在所有迭代中使用相同的计算值,则绝对应在循环上方对其进行计算-这比最小化其作用域更重要。

澄清compute()一下:只要总是返回相同的值,这个

int value = compute();
while (something) {
    doSomething(value);
}

比这更聪明:

while (something) {
    int value = compute();
    doSomething(value);
}

2
您如何在循环中定义变量并在循环之前分配变量?
蒙面男子

6
@MaskedMan,我认为您误会了。Kilian的意思是,如果您有一个在循环的每次迭代期间分配了相同值的变量,例如,将相同的date变量设置为1/1/1900,则应声明该变量,并应在循环之前分配该值。
ps2goat

2
我认为最近二十年来(在本科编译器课程之外)没有编写过一个编译器,它不会弄清楚您在每次迭代中分配相同的值并将该分配移出循环。
TMN

14
@tmn:切勿让编译器以更大的代码清晰度来完成您可以轻松完成的工作。
罗伯特·哈维

10
@TMN,不一定。仅当编译器可以证明计算无副作用时,这种优化才有可能。
Paul Draper

16

复杂类型具有非平凡的构造函数和析构函数。

这些将在循环体的开始和结束处被调用(因为它已初始化且超出范围)。如果初始化很昂贵,例如需要分配一些内存,则应避免这种情况。

但是对于琐碎的类型,这没问题。分配和释放本身只是从堆栈指针中添加和减去一个值。(将对其进行优化)


谢谢,正是我要的答案!
gebbissimo

6

好吧,他的建议有点太简单了(这是一种轻描淡写)。
好的想法谁在乎坏的想法一直不可能

  1. 只要重用比销毁旧的和创建新的便宜,就应该遵循它。

    #include <iostream>
    #include <string>
    
    int main() {
        std::string s; // Don't needlessly free the buffer
        while ((std::cin >> s))
            std::cout << s;
    }
  2. 当对性能无关紧要时,应将其视为样式问题。

    #include <stdio.h>
    #include <stdlib.h>
    int f(int, int);
    
    int main() {
        for (int i = 0; i < 100; ++i) {
            int x = rand(); // Declared here so you don't need to hunt it down.
            printf("%d => %d\n", x, f(x-1, x+i));
        }
    }
  3. 当它具有较差的性能或错误的语义时,您真的应该避免使用它。

    #include <iostream>
    #include <string>
    std::string generate(int);
    
    int main() {
        for(int i = 0; i < 100; ++i) {
            std::string s = generate(i); // Using copy-ellision here
            std::cout << s;
        }
    }
  4. 如果使用的类型既不允许交换,也不允许移动分配或复制分配,则不能遵循它。

    #include <iostream>
    #include <puzzle>
    
    int main() {
        for (int i = 0; i < 100; ++i) {
            Puzzle x(i); // Puzzle is an immutable class. For whatever reasons.
            std::cout << x;
        }
    }

2
根据您对“循环”的定义,可以将1更改为for (std::string s; std::cin >> s;) ...“ outside” ,并且仍然是“ outside”
Caleth 18/02/16
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.