如何解决C ++ std transform多次调用复制构造函数
在将地图元素复制到向量中的代码实现期间,我发现std::transform
多次调用了自定义类的复制ctor,尽管事先保留了向量大小。因此,我比较了执行此操作的不同方法,并发现最好的方法是简单的for
循环。所以我的问题是:这些算法真的更昂贵吗?如果是这样,它们的优势是什么?还是少量元素无关紧要?这是我的测试代码:
class A
{
public:
A() {}
A(int ai) : i(ai) {}
A(A& a) : i(a.i) { std::cout << "copy ctor " << i << std::endl; }
A(const A& a) : i(a.i) { std::cout << "copy const ctor " << i << std::endl; }
A(A&& a) : i(std::move(a.i)) { std::cout << "move ctor " << i << std::endl; }
// I removed overloaded operators because they are not called here...
private:
int i;
};
std::map<int,A> m;
m.insert(std::make_pair(0,A(7)));
m.insert(std::make_pair(1,A(3)));
m.insert(std::make_pair(2,A(1)));
std::vector<A> vec;
vec.reserve(m.size());
std::transform(m.begin(),m.end(),std::back_inserter(vec),[](const std::pair<int,A> & p) { return p.second; }); // 3 calls for each ctor
//... clean up and reserve vec
std::for_each(m.begin(),[&vec](const std::pair<int,A> & p) { vec.push_back(p.second); }); // 2 calls for each ctor
//... clean up and reserve vec
for (const auto & p : m) // 1 call for each ctor
{
vec.emplace_back(p.second);
}
解决方法
"POSIXt"
中的元素类型为std::map
。
在您的示例中,使用不带const的std::pair<const Key,Value>
,因此您需要复制该对。这将在前两个解决方案中添加一个副本。如果将其更改为std::pair<int,A>
,则在第一次迭代中可以看到2个构造函数调用,而在第二次迭代中只能看到一个(与for循环相当)。
对于第一次迭代,您现在有1个副本和一个动作。这是因为您的lambda需要复制A,然后back_inserter移动将其构造到向量中。通常,我不担心额外的举动,因为它们应该很便宜。
但是,您可以摆脱它。我们可以通过例如将返回类型指定为引用来强制lamba不复制A实例。因此,现在back_inserter插入时将不得不复制,仅此而已。
此版本的代码为每个解决方案的每个元素做一个副本:
std::pair<const int,A>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。