为什么这么多人打电话来复制缺点,我希望只有最后九个呢?或者甚至根本不回归价值优化。
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
答案 0 :(得分:10)
你的矢量vc
必须增长几次。每次执行此操作时,它会分配更大的内存块,并复制原始元素。
您可以使用std::vector::reserve
保留足够的空间来阻止它这样做。
vector<C> vc;
vc.reserve(vi.size());
答案 1 :(得分:4)
从程序输出中可以看到,当一个新元素被添加到向量中时,内存将被重新分配,并且已经存在的向量元素将被复制到新位置。
在运行算法之前,您可以保留足够的内存,以避免重新分配内存。
vector<C> vc;
vc.reserve( vi.size() );
在这种情况下,可以避免复制构造函数的redundent调用。
但这不是完整的故事。:)
C类有一个转换构造函数
C(int i) : _i(i) {}
它允许通过替换使用lambda表达式算法vc
而不使用lambda表达式的算法std::transform
的调用来简化向量std::copy
的元素创建。例如
std::copy( vi.begin(), vi.end(), std::back_inserter( vc ) );
但即使这不是完整的故事。:)
当您使用std::transform
或std::copy
时,会使用两个构造函数:带有参数的构造函数和复制构造函数。
您可以避免使用复制构造器并获得更有效的结果。简单地使用方法push_back
emplace_back
如何使用此方法?
最简单的方法是使用基于范围的for语句
for ( int x : vi ) vc.emplace_back( x );
它足够清晰可读。
如果您想使用标准算法,可以编写
std::for_each( vi.begin(), vi.end(), [&vc]( int x ) { vc.emplace_back( x ); } );
在这两种情况下,只调用带参数的构造函数,避免调用复制构造函数。
自己检查一下。:)