在循环内声明变量,是好习惯还是坏习惯?

2023-12-30

问题#1:在循环内声明变量是好习惯还是坏习惯?

我读过有关是否存在性能问题的其他线程(大多数人说不),并且您应该始终将变量声明为靠近它们将要使用的位置。我想知道是否应该避免这种情况,或者是否确实是首选。

Example:

for(int counter = 0; counter <= 10; counter++)
{
   string someString = "testing";

   cout << someString;
}

问题2:大多数编译器是否意识到该变量已经被声明并只是跳过该部分,或者它实际上每次都在内存中为其创建一个位置?


This is 出色的实践。

通过在循环内创建变量,可以确保它们的范围仅限于循环内部。不能在循环之外引用或调用它。

这边走:

  • 如果变量的名称有点“通用”(如“i”),则不存在将其与代码中稍后某个位置的另一个同名变量混合的风险(也可以使用-WshadowGCC 警告说明)

  • 编译器知道变量范围仅限于循环内部,因此如果在其他地方错误地引用了该变量,编译器将发出正确的错误消息。

  • 最后但并非最不重要的一点是,编译器可以更有效地执行一些专用优化(最重要的是寄存器分配),因为它知道变量不能在循环之外使用。例如,无需存储结果以供以后重复使用。

简而言之,你这样做是对的。

但请注意,该变量是不应该保留其价值每个循环之间。在这种情况下,您可能需要每次都对其进行初始化。您还可以创建一个更大的块,包含循环,其唯一目的是声明必须在从一个循环到另一个循环之间保留其值的变量。这通常包括循环计数器本身。

{
    int i, retainValue;
    for (i=0; i<N; i++)
    {
       int tmpValue;
       /* tmpValue is uninitialized */
       /* retainValue still has its previous value from previous loop */

       /* Do some stuff here */
    }
    /* Here, retainValue is still valid; tmpValue no longer */
}

对于问题#2: 当函数被调用时,变量被分配一次。事实上,从分配的角度来看,它(几乎)与在函数开头声明变量相同。唯一的区别是范围:变量不能在循环之外使用。甚至有可能该变量没有被分配,只是重新使用一些空闲槽(来自作用域已结束的其他变量)。

范围受到限制且更精确,优化就会更准确。但更重要的是,它使您的代码更安全,在阅读代码的其他部分时需要担心的状态(即变量)更少。

即使在外部也是如此if(){...}堵塞。通常,而不是:

    int result;
    (...)
    result = f1();
    if (result) then { (...) }
    (...)
    result = f2();
    if (result) then { (...) }

写起来更安全:

    (...)
    {
        int const result = f1();
        if (result) then { (...) }
    }
    (...)
    {
        int const result = f2();
        if (result) then { (...) }
    }

差异可能看起来很小,尤其是在这么小的例子上。 但在更大的代码库上,它将有所帮助:现在传输一些代码没有风险result价值来自f1() to f2()堵塞。每个result严格限制在自己的范围内,使其作用更加精准。从评论者的角度来看,这要好得多,因为他拥有的更少长程状态变量担心和跟踪。

甚至编译器也会提供更好的帮助:假设将来在代码发生一些错误更改之后,result没有正确初始化f2()。第二个版本将简单地拒绝工作,在编译时声明清晰的错误消息(比运行时更好)。第一个版本不会发现任何东西,结果是f1()将简单地进行第二次测试,对结果感到困惑f2().

补充信息

开源工具CppCheck http://cppcheck.sourceforge.net/(C/C++ 代码的静态分析工具)提供了有关变量最佳范围的一些极好的提示。

回应分配评论: 上述规则在 C 中适用,但可能不适用于某些 C++ 类。

对于标准类型和结构,变量的大小在编译时已知。 C 中没有“构造”这样的东西,因此当调用函数时,变量的空间将简单地分配到堆栈中(没有任何初始化)。这就是为什么在循环内声明变量时成本“为零”的原因。

然而,对于 C++ 类,有一个构造函数的东西我知之甚少。我想分配可能不会成为问题,因为编译器应该足够聪明来重用相同的空间,但初始化可能会在每次循环迭代时发生。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在循环内声明变量,是好习惯还是坏习惯? 的相关文章

随机推荐

  • 使用 Graph API 或 FQL 将所有照片包含在单个 Facebook Feed 帖子中?

    我正在使用 Facebook 图形 API 来获取我最近的帖子并通过 graph facebook com me feed 提要项目 我遇到的问题是 当提要对象是包含多张照片的帖子时 结果中的数据仅包含其中一张照片的信息 并且我似乎无法找到
  • iPhone:我需要实现 UIScrollViewDelegate (或任何委托)的所有方法吗

    假设我将 UIViewController 设为 UIScrollViewDelegate 我是否需要实现委托的所有方法 或者我可以只实现我关心的 1 个方法吗 If you cmd click在 Xcode 中 你声明你实现了该协议
  • UIScrollView 在 iPhone/iPad 上旋转时禁用滚动

    我使用 UIScrollView 和其中的图像作为每页分页一个图像 我在旋转时遇到问题iPhone http en wikipedia org wiki IPhone 当我旋转iPhone时 scrollViewDidScroll 滚动视图
  • requests.get(url) 未返回此特定 url

    我正在尝试使用 requests get url text 从该网站获取 HTML 但是 当使用此特定网址调用 requests get url 时 无论我等待多久 它都不会返回 这适用于其他网址 但这个网址给我带来了麻烦 代码如下 fro
  • @DirtiesContext 不适用于 @Nested 测试

    经过几个小时的谷歌研究后我仍然不知道如何使用 DirtiesContext with Nested类 假设以下集成测试类 ExtendWith SpringExtension class SpringBootTest AutoConfigu
  • VS 2019 更新后运行 azure 函数时出现调试配置文件不存在错误

    更新到版本 16 10 0 后无法从 Visual Studio 2019 调试 azure 函数 出现以下错误 此问题的问题是未正确安装引用的 Azure Function Tools 版本 因此 当它被部分下载时 它甚至不会尝试重新安装
  • 如何告诉CRAN自动安装包依赖项?

    我在 R 中开发了一个包 当我在本地计算机中检查并构建它时 它可以正常工作 但是当我在 CRAN 中尝试时 出现包依赖错误 我的包依赖于其他包的两个功能 如果我在下面列出其他包description using Depends or imp
  • JS中如何将字符串类型的十六进制转换为数字?

    例如 假设我有一个十六进制 0xdc 如何转换这个十六进制string转为十六进制Number输入JS 从字面上看只是丢失了引号 这Number 构造函数和parseInt 只是将其转换为 0 到 255 之间的整数 我只是想要0xdc E
  • 有效统计 MongoDB 中出现的百分比

    所以 我正在修改 MongoDB 并且试图获得count 聚合查询可以适当扩展 以便我可以轻松计算文档中某些值在整个集合中出现的百分比 我有一个结构如下的文档 foo bar moo cow values alpha true beta f
  • 在数据库中更改后,Prestashop 重定向到旧域

    我正在尝试创建 prestashop 1 6 电子商店的副本 用于从domain com 到 dev domain com 的开发目的 我遵循的过程是 禁用缓存和编译 将文件从domain com复制到dev domain com 从dom
  • 如何加速向量叉积计算

    嗨 我是这里的新手 正在尝试使用 numpy 进行一些计算 我在一次特定的计算中经历了很长的时间 并且无法找到任何更快的方法来实现同样的事情 基本上它是射线三角形相交算法的一部分 我需要计算两个不同大小的矩阵的所有向量乘积 我使用的代码是
  • aws ecs 优化的 AMI 中的私有 docker 注册表身份验证不成功

    我正在编写一个 terraform 脚本来创建 ECS 自动缩放集群 我创建了一个集群并向其中添加了 ec2 容器实例 我的任务定义文件包含来自私有 docker 存储库的图像 我浏览了 aws 官方文档并找到了一个页面私人登记认证 htt
  • 通过 Geodjango 中的几何交集关联两个模型

    在 GeoDjango 中 两个有两个包含几何字段的模型 from django contrib gis db import models class Country models Model territory models MultiP
  • AudioKit:我可以在不调用 AudioKit.stop() 的情况下禁用 AKMicrophone 吗?

    我有一个具有两个功能的应用程序 一个扮演一个AKMetronome并允许当应用程序不在前台时进行后台播放 另一个是调谐器功能 它使用AKMicrophone 仅当应用程序位于前台时才需要处于活动状态 这些功能可以同时使用 调谐器处于活动状态
  • 为什么我不能在同一结构中存储值和对该值的引用?

    我有一个值 我想存储该值和对的引用 我自己的类型中该值内的某些内容 struct Thing count u32 struct Combined lt a gt Thing a u32 fn make combined lt a gt gt
  • 如何将初始参数传递给 django 的 ModelForm 实例?

    我遇到的具体情况是这样的 我有一个交易模型 其中包含以下字段 from to 两者都是ForeignKeys to auth User型号 和amount 在我的表单中 我想向用户展示 2 个要填写的字段 amount and from t
  • 从命令行运行 Eclipse 项目

    我在从命令行编译和运行 Eclipse java 项目时遇到两个问题 当我刚刚从 Eclipse IDE 运行时 这工作得很好 我尝试过谷歌搜索 但无法真正让事情发挥作用 任何帮助深表感谢 问题 1 当我尝试从 java 文件所在目录以外的
  • 在所有路线上反应加载屏幕?

    我了解如何获得旋转屏幕state and componentDidMount 但我将如何在所有路线之间创建一个加载屏幕而无需编写componentDidMount 在每个组件中 我的 app js 文件 class App extends
  • 无法在 WebView 中输入内容

    我在与某个人交互时遇到问题WebView 我正在显示一个 HTML 登录表单WebView我无法在表单的任何输入字段内键入内容 我确实可以与链接 选择框 按钮等进行交互 这是我的代码的示例 基本上我从 xml 中检索 Web 视图并将其设置
  • 在循环内声明变量,是好习惯还是坏习惯?

    问题 1 在循环内声明变量是好习惯还是坏习惯 我读过有关是否存在性能问题的其他线程 大多数人说不 并且您应该始终将变量声明为靠近它们将要使用的位置 我想知道是否应该避免这种情况 或者是否确实是首选 Example for int count