我在SO (特别是this)中读过几篇文章和答案,但它们没有给出我的问题的完整答案。他们倾向于关注特殊情况,在这种情况下,移动语义与复制指针一样快,但情况并不总是如此。
例如,考虑这个类:
struct Big {
map<string, unsigned> m;
vector<unsigned> v;
set<string> s;
};
这一职能:
Big foo();
如果foo
按值返回并且无法通过RVO
优化副本,编译器将应用移动语义,这意味着三个移动,每个类成员一个。如果班级成员超过3人,我就会有更多的操作。如果foo通过指针(可能是智能指针)返回Big
对象,则始终是1操作。
更有趣的是,Big
对象具有非本地生命周期:它们在应用程序的持续时间内保存在某些数据结构中。因此,您可能期望Big
对象在其生命周期中被多次移动,而在foo
返回对象之后很久,3个操作(移动语义)和1个操作(指针)的成本一直在增加性能。
考虑到这些背景信息,这里是我的问题
首先,我想确定我对移动语义性能的理解:在上面的示例中,moving Big object比复制指针慢吗?
2-假设移动语义确实较慢,我会接受通过指针返回Big objects吗?还是有更好的方法来实现速度和良好的API (我认为返回值更好)?
编辑
底线:我喜欢按值返回,因为如果我在API中引入一个指针,它们就会扩散到任何地方。所以我想避开他们。然而,我想确定性能的影响。C++是关于速度的,我不能盲目地接受移动语义,而不理解性能的影响。
发布于 2022-03-31 15:23:39
在应用程序期间保存在某些数据结构中。因此,你可能会期望大物体在它们的生命中被多次移动
我不同意这个结论。大多数数据结构的元素在内存中往往是相当稳定的。异常是无保留的std::vector
和std::string
,以及其他基于向量的结构,如平面映射。
如果foo按值返回,并且无法通过
优化副本,则为。
因此,以一种可以通过RVO优化的方式实现foo
。最好是在C++17中保证不移动。这是一个快速的,方便的API,所以你应该更喜欢。
1-首先,我想确定我对移动语义性能的理解:在上面的示例中,moving比复制指针慢吗?
这是真的。移动Big
比复制指针要慢一些。它们都是绝对意义上的轻量级操作(取决于上下文)。
当您考虑将指针返回到新创建的对象时,您还必须考虑对象的生存期以及它的存储位置。如果您正在考虑动态分配它,并返回一个指向动态对象的指针,那么您必须考虑到,动态分配可能比成员对象的几个移动要昂贵得多。而且,与std::map
和其他容器所做的所有分配相比,所有这些可能都是微不足道的,因此,所有这些考虑最终都可能无关紧要。
总结:如果你想知道什么更快,那就测量一下。如果一个实现度量的速度要快得多,那么该实现可能就是更快的实现(取决于您在度量方面的出色程度)。
https://stackoverflow.com/questions/71694935
复制相似问题