【问题标题】:Optimising Iterator Definitions优化迭代器定义
【发布时间】:2009-02-09 10:24:46
【问题描述】:

这是一个(希望如此)非常简单的问题 - 最近有人告诉我,使用 C++ 风格的初始化比传统的(更常见的)赋值要好。

所以这段代码:

std::SomeSTLContainer::const_iterator it = container.begin();
std::SomeSTLContainer::const_iterator itEnd = container.end();

会比以下“慢”或效率低:

std::SomeSTLContainer::const_iterator it ( container.begin() );
std::SomeSTLContainer::const_iterator itEnd ( container.end() );

我理解这样做的原因 - 第一个示例导致默认构造和初始化,然后是后续分配,而不是第二个示例中的特定构造和直接分配。然而,在现代处理器/编译器上,它真的有什么不同吗?

【问题讨论】:

    标签: c++ optimization stl iterator


    【解决方案1】:

    最近有人告诉我,使用 C++ 风格的初始化比传统的(更常见的)赋值要好。

    这是完全错误的。

    我理解这样做的原因 - 第一个示例导致默认构造和初始化,然后是后续分配,而不是第二个示例中的特定构造和直接分配。然而,在现代处理器/编译器上,它真的有什么不同吗?

    不,没有区别。 C++ 标准明确允许在这种情况下省略赋值,以便生成相同的代码。在实践中,所有现代 C++ 编译器都会这样做。

    此外,Charles 是对的:这永远不会调用赋值运算符,而是调用复制构造函数。但正如我所说,即使这样也不会发生。

    【讨论】:

    • 你的“不,它没有”是指我的整个第二段还是只是“它真的有影响吗?”问题? :) 如果是前者,你能直截了当地说。
    • 偏爱第二种形式的一个原因是它可以更明确地说明将要发生的事情。它可以帮助阅读代码的人了解将使用复制构造函数。
    【解决方案2】:

    你的推理不太正确。在定义中使用“=”不会导致默认构造和赋值。在“最坏”的情况下,它使用从“=”右侧生成的临时构造函数。

    如果右侧的类型是相同类型(除了常量/易失性)或被初始化对象的派生类型,那么这两种构造形式是等价的。

    【讨论】:

      【解决方案3】:

      不,通常。这是因为迭代器被编码为非常薄的包装器,而优化器在涉及到薄包装器时非常激进。例如。普通的迭代器方法只是一个简单的指针操作,函数体可以从头部获得。这使得它可以简单地内联。在这种情况下,迭代器副本在幕后可能只是一个指针副本,所以同样成立。

      【讨论】:

      • 关于迭代器的好点,但不太适用,因为即使对于更重量级的类,在两种情况下都会生成相同的代码。
      【解决方案4】:

      这真的取决于具体情况,应该应用一般的经验法则:measure

      如果这些迭代器有很多实例化(可能在嵌套和排序循环中,那些较短的构造函数很容易产生影响)。 尽管正如您所建议的那样,许多编译器已经可以自行优化它们。

      要真正确定您的编译器是否这样做,只有一种方法:测量

      【讨论】:

        【解决方案5】:
        A a = A( arg1, arg2, ... );
        

        正如鲁道夫所说,这个赋值可以用一个简单的结构来代替:它是一个结构。事实上,它会被编译成更简洁的等价物

        A a( arg1, arg2, ...);
        

        这主要是样式问题,但我不喜欢将“分配样式”结构与“初始化器样式”结构混合在一起。通过这种方式,我可以在整个代码中引入一致性。这归结为:始终使用初始化程序样式构造:)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-07-14
          • 2010-10-22
          • 2021-07-25
          • 2013-05-29
          • 1970-01-01
          • 1970-01-01
          • 2015-02-04
          相关资源
          最近更新 更多