繁体   English   中英

如何最小化列表构造函数(复制构造函数)的调用次数?

[英]How to minimize the times that list constructor (either copy-constructor ) is called?

我有以下比较方法。 该方法比较并返回diff结果。

我想最小化结果列表被复制的次数(到时间和赋值)。

一种方法是为结果添加额外的引用参数,但我喜欢utils函数是关闭的(它们不会改变值),所以我宁愿避免这种情况。

通过在赋值中使用const&可以避免一个副本

const& list<uint32> diff = getDiffNewElements (...)

,还可以通过一种方法避免本地复制到时态吗?

diff方法:

list<uint32> getDiffNewElements(const list<Row>& src ,const list<Row>& dst) {
    list<uint32> result;

        ... Do Some compare

        return result;
}

您提供的代码中可能有两个副本。 一个函数内部,从变量result到返回的对象。 如果功能的复杂性允许,NRVO将负责这一点。 如果看起来有一个return语句,那么编译器将忽略该副本(假设您没有使用编译器标志禁用它并且您启用了一些优化级别)。

第二个潜在副本位于调用者中,从返回值到最终存储。 编译器几乎总是忽略该副本,并且在这里做的比在NRVO情况下更简单:调用约定(我知道的所有调用约定)确定调用者为返回的对象保留空间,并且它将指向该位置的隐藏指针传递给该函数。 该函数依次使用该指针作为第一个副本的目标。

函数T f()转换为void f( uninitialized<T>* __ret ) (没有uninitialized<> ,但是请耐心void f( uninitialized<T>* __ret ) )并且函数的实现在复制时使用该指针作为目标return声明。 在调用者站点上,如果你有T a = f(); 编译器会将它转换为T a/*no construction here*/; f(&a); T a/*no construction here*/; f(&a);

问题中有一些有趣的代码似乎表明你过去曾误导过: const list<uint32>& diff = getDiffNewElements(...) 使用引用而不是直接存储值(如list<uint32> diff = getDiffNewElements(...) )对所创建的副本数量完全没有影响。 getDiffNewElements仍然需要复制 (或删除副本)到返回的对象,并且该对象位于调用者的范围内。 通过获取const引用,您告诉编译器您不希望直接命名该对象,而是将其保留为范围中的未命名对象,并且您只想使用对它的引用。 在语义上它可以转换为:

T __unnamed = getDiffNewElements(...);  // this copy can be elided
T const& diff = __unnamed;

编译器是免费的,可能会优化引用,使用标识符diff作为__unnamed的别名而不需要额外的空间,因此通常它不会比替代方案更糟糕,但代码稍微复杂一些没有任何优势。

很久以前,当我有时间的时候,我开了一个博客并撰写了几篇关于价值语义的文章,(N)RVO和copy elision。 你可能想看看。

你看错了方向。 您的getDiffNewElements方法不会创建不必要的副本,因为现代编译器会执行RVO (注释中指出了这一点,但如果您的编译器没有执行RVO,那么您无需执行任何操作,您的const&也无济于事)。 您可以优化此函数的方法是返回vector而不是list ,因为您可以在vector上调用reserve ,并在每次push_back新元素时避免内存分配。 list不会使用默认分配器预分配内存,并且没有reserve方法来执行此操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM