内置类型具有移动语义吗?
内置类型具有移动语义吗?
考虑以下代码:\n
#includeusing namespace std; void Func(int&& i) { ++i; } int main() { int num = 1234; cout << "Before: " << num << endl; Func(std::move(num)); cout << "After: " << num << endl; }
\n它的输出结果是:\n
Before: 1234 After: 1235
\n显然,`i`在`Func`内部被修改了,因为它在被`std::move`“转换”为右值引用后绑定到了参数`i`上。\n我的观点:\n移动一个对象意味着将资源的所有权从一个对象转移到另一个对象。然而,内置类型没有持有任何资源,因为它们本身就是资源。将它们持有的资源转移是没有意义的。正如示例所示,`num`的值被修改了,它所拥有的资源——即它自身——被修改了。\n内置类型是否具有移动语义?\n此外,在被移动后(如果有的话),内置类型对象是否具有良定义的行为?
内置类型是否具有移动语义?
是的,示例中显示的行为是标准允许的唯一行为。这是因为std::move
并不进行移动操作,真正进行移动的是移动构造函数和移动赋值运算符。
std::move
只是将左值转换为右值引用,以便可以绑定到右值引用参数。它不会调用任何构造函数或其他操作。值类别的改变是在类型级别进行的,运行时什么都不会发生。
右值引用仍然是引用,它们引用的是原始对象。通过给定的引用,该函数递增了原始整数。
如果函数通过引用接收参数,则不会发生复制或移动:原始对象绑定到引用上。
如果函数通过值接收参数,则可能会进行移动操作。
然而,基本类型没有移动构造函数,因此移动操作会退化为复制操作。
“如果函数通过引用接收参数,则不会发生复制或移动:原始对象绑定到引用上。如果函数通过值接收参数,则可能会进行移动。”我感到困惑--似乎恰好相反。如果我们传递值,那么原始对象不能被更改,因为我们只是使用副本。如果我们通过引用传递,则可以进行移动:请参阅此页面上的第一个示例。learncpp.com/cpp-tutorial/15-4-stdmove我确信我对您的意思有所误解。
如果您通过值接收参数,则参数可能会从参数中进行移动构造。因此,原始对象可以更改。如果您通过引用接收参数,则在参数传递过程中不会进行移动操作。如果以后进行移动操作,则是另一回事。
“after”输出是定义行为还是未定义行为?我认为“after”输出尝试访问已经被移动的东西(num)。
当您在后续使用num
时,这是定义良好的行为。