当前位置: 首页 > 知识库问答 >
问题:

为什么我必须对rvalue引用调用move?

蒯硕
2023-03-14

在下面的代码中,为什么第一个调用mkme=mvme_rv不分派到T&; 运算符=(const t&&)

#include <iostream>
#include <string>
#include <vector>

using namespace std;
using T = vector<int>;

int main()
{
  T mvme(10, 1), mkme;
  T&& mvme_rv = move(mvme); // rvalue ref?
  mkme = mvme_rv;           // calls T& operator=(const T&)?
  cout << mvme.empty();     // 0
  mkme = move(mvme_rv);     // calls T& operator=(const T&&)?
  cout << mvme.empty();     // 1
}

共有2个答案

尉迟正奇
2023-03-14

这行代码:

mkme = mvme_rv;

是副本,因此将使用副本赋值(T&;operator=(const T&;))。 这方面的关键是,这两个对象都可以在之后使用,并且如果实现正确,应该提供两个相同的对象。

相比之下,这行代码:

mkme = move(mvme_rv);

是移动赋值(T&;operator=(const T&;))。 按照惯例,这将破坏MVME_RV对象(或至少清除它),并使MKME基本上与MVME_RV之前的内容相同。

实际上,T&&意味着一个临时对象(也就是xvalue)--不会持续的对象。 std::move方法基本上将对象强制转换为临时对象(这种措辞归功于@richard-Hodges)。 然后,这可以在移动分配方法中使用。

最后,为了回答为什么mkme=mvme_rv不分派到t&; operator=(const t&&):这是因为MVME_RV不是临时对象(也就是xavalue)。

有关XValues的详细信息:http://en.cppreference.com/w/cpp/language/value_category

池阳伯
2023-03-14

正如skypjack正确指出的那样,通过对象的名称访问对象总是导致一个lvalue引用。

这是一个安全功能,如果你仔细考虑,你会意识到你很高兴它。

如您所知,std::move只是将L值引用强制转换为R值引用。 如果我们立即使用返回的r值引用(即未命名),那么它仍然是r值引用。

这意味着r值只能在代码中提到move(x)的位置使用。 从代码阅读器的角度来看,现在很容易看到X的状态在哪里变得未定义。

所以:

 1: auto x = make_x();
 2: auto&& r = std::move(x);
 3: // lots of other stuff
35: // ...
54: // ...
55: take_my_x(r);

不管用。 如果是这样,维护代码的人将很难看到(并记住)x(定义在第1行)通过第2行的引用在第55行进入未定义状态。

这是非常明确的:

 1: auto x = make_x();
 2: //
 3: // lots of other stuff
35: // ...
54: // ...
55: take_my_x(std::move(x));
 类似资料:
  • 问题内容: 我创建了一个用于显示工具提示的指令: 对应功能: 应用于此: 这是我观点的一部分,由拥有者的控制器处理 为什么必须调用才能将更改应用到,该更改是早先声明和初始化的? 问题答案: 因为附加到事件的回调超出了angular的范围;angular不知道该函数何时运行/结束,因此摘要循环永远不会运行。 调用或告诉angular更新绑定并触发任何手表。

  • 问题内容: 每个人都告诉我“使用super.viewDidLoad()因为它就是这样”或“我一直那样做,所以要保留它”,“如果不叫super就是错误的”等。 我只发现了一些有关Objective-C用例的主题,这些主题并没有那么启发性,但是我正在Swift 3中进行开发,所以有什么专家可以给我一个很好的详细解释吗? 这是一种良好实践的案例还是有任何隐藏的影响? 问题答案: 通常,最好为您覆盖的所有

  • 关于在最新版本的GCC和Clang中编译有几个问题:实验::filessystems链接器错误 但是现在< code>filesystem已经被c 17接受,所以不再需要< code>experimental或< code>-lstdc fs标志,对吗? 错了,我甚至不能 只给了我< code >实验版本,我怎么能包括正式接受的版本呢?

  • 假设一个函数有两个重载 然后在另一个函数的主体中 过载<代码>f(T 这让我非常惊讶。一个带有签名

  • 我有方法 在正文中,我编写了一些HashMap的键集 看起来还可以,但如果我想重复这个代码 我得用try/catch来包围它。像这样 我不明白为什么

  • 我正在开发一个使用JFreeChart渲染图表的Web应用程序。但是,当服务器没有安装任何中文字体时,即使我设置了字体,JFreeChart也不会显示汉字。 然后我写了一个小的测试代码,发现在绘制图表之前添加这行代码可以解决问题。 所以我的问题是- > 为什么即使我从File创建字体,我也必须将字体注册到JVM?这是否意味着JFreeChart不使用我直接设置的字体? 当我将程序部署到服务器时,即

  • 问题内容: 当我想在当前范围内引用该方法时,我仍然需要指定类名(对于静态方法)或在 运算符之前。例如,我需要写: 对于来说,这并不是什么大问题,但是对于静态方法而言,有时显得有些拥挤,因为类名可能会很长。如果编译器允许我直接编写代码,那就太好了: 但是Java-8编译器不允许这样做。对我来说,如果用与普通方法调用相同的方式解析类/对象名称,那似乎是非常一致的。这也将支持方法引用的静态导入,这在某些

  • 根据文档,newInstance()返回一个T:https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#newInstance() 所以,如果我有一个返回T的方法,为什么我必须强制转换构造函数的返回。newInstance()到T?