Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么标准在移动分配运算符中使用exchange?_C++ - Fatal编程技术网

C++ 为什么标准在移动分配运算符中使用exchange?

C++ 为什么标准在移动分配运算符中使用exchange?,c++,C++,我今天在试验std::exchange。根据关于std::exchange的CPPPreference,此函数可用于移动构造函数和移动赋值运算符。CPP参考中的示例如下: struct S { int* p; int n; S(S&& other) :p{std::exchange(other.p, nullptr)} ,n{std::exchange(other.n, 0)} {} S& operator=(S&&

我今天在试验std::exchange。根据关于std::exchange的CPPPreference,此函数可用于移动构造函数和移动赋值运算符。CPP参考中的示例如下:

struct S
{
  int* p;
  int n;

  S(S&& other)
    :p{std::exchange(other.p, nullptr)}
    ,n{std::exchange(other.n, 0)}
  {}

  S& operator=(S&& other) {
    p = std::exchange(other.p, nullptr); // move p, while leaving nullptr in other.p
    n = std::exchange(other.n, 0); // move n, while leaving zero in other.n
    return *this;
  }
};
我有点不明白。在move构造函数中使用std::exchange是可以的,因为新的(构造的)对象将接管已经存在的(旧的)对象的内部,并且旧对象的资源指针将被赋值为nullptr值,因此在move构造函数之后,旧对象将被销毁,但资源将继续存在于新对象中

但对于move赋值操作符,我认为它的工作方式应该有所不同。受让人对象应该接管被分配对象的资源,被分配对象应该接管受让人对象的资源。在此之后,当分配的对象被销毁时,它将销毁受让人以前使用的资源。换言之,该机制应该交换资源。 在这段代码中,当分配对象的resource指针被分配为nullptr时,我们将有一个资源泄漏(过去住在受让人中的那个)。我理解正确吗?还是我遗漏了什么

我想还有一些我不知道的事情,因为这段代码在官方文档中使用。有人能帮我了解一下这里发生了什么吗?

首先,这里没有“官方文件”。cppreference很受欢迎,但它只是一个网站,是一个由社区编辑的网站。它当然不是“标准”,而且(像任何网站一样)它包含bug也不是闻所未闻的……就像这个

事实上,这是一个糟糕的例子——不仅资源没有被正确地清理,它甚至从来没有被创建过


你可以用一个更好的例子来编辑你所指的页面;这只是一个wiki。

“分配的对象应该接管受让人对象的资源”为什么?有两个对象,a和B。每个对象都分配了一个资源。如果您将B分配给A,那么A将接管B的资源。但是A最初分配的资源会发生什么变化?应将其分配给B或立即在移动分配操作员正文中删除。由于B对象最终将很快被销毁,因此它的析构函数将被调用,因此B可以接管A的资源并在B的析构函数中释放它。@YotKay,这个例子确实有些混乱。通常我们期望当一个类有指针成员时,它应该拥有指向的对象,因此它应该负责调用
delete
。但这不是必须的,结构只观察指向的对象。这可能不是我见过的最好的例子。“因为这段代码在官方文档中使用”-cppreference不是官方文档。这里有一个教训:您需要查看类的析构函数才能知道它的不变量是什么。如果不知道“清理”意味着什么,您就不知道所示示例是否包含错误。没有证据表明示例中的类应该拥有任何资源,因此不需要创建或清理它。对于像
std::reference\u wrapper
@JonathanWakely这样的非所有者类,示例中的行为是好的:我不是说示例不正确,只是说它很差。它似乎并没有展示一个班级从任何真实的方式中受益。实际上,
std::reference\u wrapper
的move-ctor被删除了。好的,所以我使用了术语“bug”,这有点强。这个示例演示了std::exchange的用法。和示例演示了从实际移动中受益的类。@LightnessRacesinOrbit
reference\u wrapper
没有已删除的移动向量,它有一个不存在的移动向量,与已删除的不同。它来自右值
T
的ctor被删除,但这是为了防止绑定对临时变量的引用,它不是move ctor。