gpt4 book ai didi

c++ - 编译器何时在 C++ 中移动/复制?

转载 作者:太空狗 更新时间:2023-10-29 23:43:56 24 4
gpt4 key购买 nike

我正在尝试更好地理解移动在 C++ 中的工作原理。编译器如何知道什么时候移动什么时候不移动?

#include <iostream>

template <typename T>
struct Container {
T value;
Container (T value): value(value) {}
Container (const Container & i): value(i.value) {
std::cout << "copying" << std::endl;
}
Container (Container && i): value(std::move(i.value)) {
std::cout << "moving" << std::endl;
}
};

void increment (Container<int> n) {
std::cout << "incremented to " << ++n.value << std::endl;
}

int main () {
Container<int> n (5);
increment(std::move(n));
std::cout << n.value << std::endl;
}

这个例子打印

moving
incremented to 6
5

所以我希望 int已被移动,但之后我不应该仍然使用它(并获得原始值)。

好的,所以也许是 int被复制是因为 value(std::move(i.value))将其复制到移动构造函数中。但是还是不明白为什么Container<int> n在它肯定被移动之后仍然存在。

最佳答案

std::move实际上只是将值更改为可以移动的右值。如果将此应用于 int它没有实际效果,因为“移动”int 没有任何意义。值(value)。 (确实该值仍然是右值;只是对 int 的右值引用通常并不比对 int 的任何其他类型的引用更有用)。

这是因为移动意味着将资源从一个对象转移到另一个对象,从而避免了复制这些资源(通过复制它们)的需要 - 因为这种复制可以不平凡;一方面,它可能需要动态内存分配。复制 int值是微不足道的,因此不需要特殊的移动语义。

因此,应用于您的示例,移动 Container<int>与复制它完全一样,当然除了输出(“移动”与“复制”)。

(请注意,即使是移动 也需要源对象在操作完成后保持有效状态 - 它不会破坏源对象,因为您似乎认为它可能应该这样做) .

至于编译器如何知道何时可以移动或复制,这是类型类别的问题。您对 std::move 的使用特别是将值的类型类别更改为 rvalue(或更具体地更改为 xvalue),并且这种类型的值可以匹配移动构造函数中的右值引用参数。一般来说,带有右值引用参数的重载优于带有非右值引用参数的重载(具体规则很复杂)。

另一种产生右值的常见方法是作为未命名的临时值 - 通过对结果未绑定(bind)到变量的对象或值执行某些操作( a + b ,其中 ab 是两者都是 int 类型,是一个简单的例子——结果是一个临时对象;它不存在于自己的变量中)。当一个更复杂的对象是临时对象时,将其移动到其最终目的地可能比复制它更有效,并且是安全的,因为移出对象的不确定状态之后无法使用。因此,此类值也是右值,并且将绑定(bind)到右值引用(并且可能会被移动)。

关于c++ - 编译器何时在 C++ 中移动/复制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38771462/

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