[英]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.