gpt4 book ai didi

c++ - 为什么 C++11 会按值移动构造函数拷贝?

转载 作者:太空狗 更新时间:2023-10-29 20:26:20 25 4
gpt4 key购买 nike

我原以为下面的例子会和 std::map::emplace() 有相同的结果,但事实并非如此:

struct MoveTest {
MoveTest():
var(true)
{
cout << "ctor: " << static_cast<void*>(&var) << endl;
}

MoveTest(MoveTest&& mt):
var(std::move(mt.var))
{
cout << "move ctor: " << static_cast<void*>(&var) << endl;
}

bool var;
};


int main() {
map<int, MoveTest> mtest;
mtest.insert(make_pair(1, MoveTest()));
return 0;
}

输出:

ctor: 0x7fff12e4e19b
move ctor: 0x7fff12e4e194
move ctor: 0x25f3034

MoveTest::var 在每次移动中都有不同的地址。它看起来不像是“移动”。我的代码或理解有什么问题?

最佳答案

对于您定义的 MoveTest,实际上并没有多少移动构造函数(或赋值运算符)可以优化(或者通常可以优化——它真正能做的就是从源复制到目标)。

当一个对象包含指向(例如)分配在堆上的一堆外部内存的指针时,移动通常是一个巨大的胜利。在这种情况下,移动构造函数/赋值运算符基本上可以进行浅拷贝(即,仅从移出对象中获取指针)而不是深拷贝(复制该指针引用的所有数据)。

例如:

class move_tst {
int *buffer;
static const int size = 1024 * 1024;
public:
move_tst() {
buffer = new int[size];
std::iota(buffer, buffer + size, 0);
}

move_tst(move_tst const &other) {
buffer = new int[size];
std::copy_n(other.buffer, size, buffer);
}

#ifdef MOVE
move_tst(move_tst &&other) {
buffer = other.buffer;
other.buffer = nullptr;
}
#endif

~move_tst() {
delete [] buffer;
}
};

警告:我在这里使用了 new 的原始调用和原始指针,因此没有涉及任何其他内容,我们也不会(例如)获得智能指针提供的移动语义。对于正常情况下的正常代码,您应该使用其中任何一个(原始指针或 new 的原始调用,我的意思是)。

编辑:就 std::move 所做的而言,它实际上并没有自己做一个移动——它只是表示你不再关心一个值,所以它有资格成为移动的来源,即使这破坏了它的值(value)。

例如,对于上面的类,您可以进行如下测试:

for (int i = 0; i < 1000; i++) {
move_tst src;
move_tst dst =src;
}

...并将其与:

for (int i = 0; i < 1000; i++) {
move_tst src;
move_tst dst = std::move(src);
}

没有 std::movedst 将被创建为 src 的拷贝,但有 std::move,它将能够从 src 移动到 dst

关于c++ - 为什么 C++11 会按值移动构造函数拷贝?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20134278/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com