从一个堆栈移动到另一个堆
Move from stack to heap
我正在尝试调用一些函数,其中包括将元素添加到向量(按值传递的参数):
std::vector<Val> vec;
void fun( Val v )
{
...
vec.push_back(std::move( v ));
...
}
问题是:移动语义有什么好处吗?
我对构造新的向量元素时变量将从堆栈"移动"到堆感到困惑:似乎它只是被复制。
移动而不是复制是否有任何好处实际上取决于Val
的实现。
例如,如果Val
的复制构造函数的时间复杂度为 O(n),但其移动构造函数的复杂度为O(1)(例如:它只包括更改几个内部指针),那么可能会有性能优势。
在以下Val
实现中,移动而不是复制不会有任何性能优势:
class Val {
int data[1000];
...
};
但对于下面的一个,它可以:
class Val {
int *data;
size_t num;
...
};
如果 std::move 允许底层对象将指针从一个移动到另一个; 而不是(在复制中所做的)分配一个新区域,并复制可能是大量内存的内容。 例如
class derp {
int* data;
int dataSize;
}
data和dataSize可以在移动中交换;但副本可能要贵得多。
但是,如果你只有一个整数集合;移动和复制将相当于同一件事;除了对象的旧版本应该无效;无论这在该对象的上下文中应该意味着什么。
移动是对对象内部存储的盗窃(如果适用)。许多标准容器都可以从中移动,因为它们在堆上分配存储,这对于"移动"来说是微不足道的。在内部,发生的事情如下所示。
template<class T>
class DumbContainer {
private:
size_t size;
T* buffer;
public:
DumbContainer(DumbContainer&& other) {
buffer = other.buffer;
other.buffer = nullptr;
}
// Constructors, Destructors and member functions
}
如您所见,对象不会在存储中移动,"移动"纯粹是从容器other
到this
的概念。事实上,这是优化的唯一原因是因为对象保持不变。
堆栈上的存储无法移动到另一个容器,因为堆栈上的生存期与当前范围相关联。例如,std::array<T>
将无法将其内部缓冲区移动到另一个阵列,但如果T
堆上有存储可以传递,则仍然可以有效地移动它。例如,从std::array<std::vector<T>>
移动必须构造vector
对象(array
不可移动),但vector
将廉价地将其托管对象移动到新创建的array
的vector
。
因此,来到您的示例,如果Val
是可移动对象,则如下所示的函数可以减少开销。
std::vector<Val> vec;
void fun( Val v )
{
...
vec.emplace_back(std::move( v ));
...
}
你不能摆脱构造vector
,在容量填满时分配额外的空间,或者在vector
内构造Val
对象,但如果Val
只是一个指向堆存储的指针,那么它可以在不实际窃取另一个向量的情况下尽可能便宜。如果Val
不可移动,则不会通过将其转换为右值来丢失任何内容。这种类型的函数签名的好处是调用方可以决定他们是要复制还是移动。
// Consider the difference of these calls
Val v;
fun(v);
fun(std::move v);
第一个将调用Val
的复制构造函数(如果存在),否则将无法编译。第二个将调用移动构造函数(如果存在),否则将调用复制构造函数。如果两者都不存在,则不会编译。
- 如果需要转换,我可以在读取参数的同时将其移动到另一个参数吗?
- 将 std::array 移动到另一个 std::array
- 如何在不复制的情况下将一个向量移动到另一个向量中
- 为什么在 std::map 上移动无法将元素从一个映射移动到另一个映射
- 如何将所有指针从一个向量移动到另一个向量?
- 如何有效地将(一些)项目从一个std::map移动到另一个std::map
- 如何将"this"的生命周期移动到C++中的另一个对象中?
- 基于范围的 for 循环将对象移动到另一个容器中?
- 将列表的对象C++移动到另一个对象
- 如何将文件移动到Qt中的另一个现有目录
- C++将所有文件从一个目录移动到另一个目录
- 发送到另一个窗口的鼠标移动消息不执行任何操作
- 将对象从一个 std::d eque 移动到另一个的更好方法
- 如果我尝试将对话框从一个项目移动到另一个项目,我是否需要从 rc 文件中复制 DESIGNINFO、对话框信息和AFX_
- Qt 创建者在我将项目移动到另一个地方后仍然使用源项目
- 从一个堆栈移动到另一个堆
- 当设置对象等于另一个函数的返回值时,为什么要调用移动构造函数/分配
- 使用 C++98 将矢量的一部分移动(而不是复制)到另一个矢量
- 将过滤器中的所有.cpp和.h移动到另一个项目并更正其文件夹位置
- C 可以使用MOVE SEMATICS将数据从一个向量移动到另一个向量