为什么在变换/复制矢量的同时复制这么多
why so many copying while transforming/copying vector
为什么有这么多复制cons的调用,我预计只有最后九个?甚至根本不需要返回值优化。
struct C
{
int _i;
C(int i) : _i(i) {}
C(const C& other) { cout << "copy cons from " << other._i << " to " << _i << endl; _i = other._i; }
};
int _tmain(int argc, _TCHAR* argv[])
{
vector<int> vi{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
vector<C> vc;
transform(vi.begin(), vi.end(), back_inserter(vc),
[](int i)
{
return C(i);
});
}
输出:
copy cons from 1 to - 842150451
copy cons from 1 to - 842150451
copy cons from 2 to - 842150451
copy cons from 1 to - 842150451
copy cons from 2 to - 842150451
copy cons from 3 to - 842150451
copy cons from 1 to - 842150451
copy cons from 2 to - 842150451
copy cons from 3 to - 842150451
copy cons from 4 to - 842150451
copy cons from 1 to - 842150451
copy cons from 2 to - 842150451
copy cons from 3 to - 842150451
copy cons from 4 to - 842150451
copy cons from 5 to - 842150451
copy cons from 6 to - 842150451
copy cons from 1 to - 842150451
copy cons from 2 to - 842150451
copy cons from 3 to - 842150451
copy cons from 4 to - 842150451
copy cons from 5 to - 842150451
copy cons from 6 to - 842150451
copy cons from 7 to - 842150451
copy cons from 8 to - 842150451
copy cons from 9 to - 842150451
您的向量vc
必须增长几倍。每次这样做时,它都会分配一个更大的内存块,并复制原始元素。
您可以通过使用std::vector::reserve
保留足够的空间来阻止它这样做。
vector<C> vc;
vc.reserve(vi.size());
从程序输出中可以看出,当一个新元素被添加到向量中时,内存会被重新分配,向量中已经存在的元素会被复制到新的位置。
您可以在运行算法之前保留足够的内存,以避免内存重新分配。
vector<C> vc;
vc.reserve( vi.size() );
在这种情况下,可以避免复制构造函数的重复调用。
但这并不是故事的全部
C类有一个转换构造函数
C(int i) : _i(i) {}
它允许通过将使用lambda表达式的算法std::transform
的调用替换为算法std::copy
而不使用lambda表达来简化向量vc
的元素的创建。例如
std::copy( vi.begin(), vi.end(), std::back_inserter( vc ) );
但即使这样也不是故事的全部
当使用std::transform
或std::copy
时,会使用两个构造函数:带参数的构造函数和复制构造函数。
你可以避免使用副本解释符,从而获得更有效的结果。简单地说,用emplace_back
方法代替push_back
方法更好
如何使用这种方法?
最简单的方法是使用基于范围的语句
for ( int x : vi ) vc.emplace_back( x );
它足够清晰易读。
如果你想使用标准算法,你可以写
std::for_each( vi.begin(), vi.end(), [&vc]( int x ) { vc.emplace_back( x ); } );
在这两种情况下,只会调用带有参数的构造函数,避免调用复制构造函数。
自己检查一下。:)
相关文章:
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 使用strcpy将char数组的元素复制到另一个数组
- 是否可以初始化不可复制类型的成员变量(或基类)
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 复制列表初始化的隐式转换的等级是多少
- 当从函数参数中的临时值调用复制构造函数时
- 有可能在Armadillo中复制MATLAB circshift方法吗
- 复制几乎为空的数组的最快方法
- 以下示例中如何避免代码复制?C++/库达
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 不能将复制初始化与隐式转换的多个步骤一起使用
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- 文件系统:复制功能的速度秘诀是什么
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 如何避免boost范围变换中的复制
- 为什么在变换/复制矢量的同时复制这么多