• <legend id='2tb9a'><style id='2tb9a'><dir id='2tb9a'><q id='2tb9a'></q></dir></style></legend>
    <tfoot id='2tb9a'></tfoot>
    <i id='2tb9a'><tr id='2tb9a'><dt id='2tb9a'><q id='2tb9a'><span id='2tb9a'><b id='2tb9a'><form id='2tb9a'><ins id='2tb9a'></ins><ul id='2tb9a'></ul><sub id='2tb9a'></sub></form><legend id='2tb9a'></legend><bdo id='2tb9a'><pre id='2tb9a'><center id='2tb9a'></center></pre></bdo></b><th id='2tb9a'></th></span></q></dt></tr></i><div id='2tb9a'><tfoot id='2tb9a'></tfoot><dl id='2tb9a'><fieldset id='2tb9a'></fieldset></dl></div>

      • <bdo id='2tb9a'></bdo><ul id='2tb9a'></ul>

        <small id='2tb9a'></small><noframes id='2tb9a'>

        在移动赋值和移动构造函数方面实现 std::swap

        时间:2024-08-14

        <small id='CMmri'></small><noframes id='CMmri'>

        <i id='CMmri'><tr id='CMmri'><dt id='CMmri'><q id='CMmri'><span id='CMmri'><b id='CMmri'><form id='CMmri'><ins id='CMmri'></ins><ul id='CMmri'></ul><sub id='CMmri'></sub></form><legend id='CMmri'></legend><bdo id='CMmri'><pre id='CMmri'><center id='CMmri'></center></pre></bdo></b><th id='CMmri'></th></span></q></dt></tr></i><div id='CMmri'><tfoot id='CMmri'></tfoot><dl id='CMmri'><fieldset id='CMmri'></fieldset></dl></div>

          <bdo id='CMmri'></bdo><ul id='CMmri'></ul>

          <legend id='CMmri'><style id='CMmri'><dir id='CMmri'><q id='CMmri'></q></dir></style></legend>

          1. <tfoot id='CMmri'></tfoot>
                    <tbody id='CMmri'></tbody>
                  本文介绍了在移动赋值和移动构造函数方面实现 std::swap的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  这是std::swap的可能定义:

                  template<class T>
                  void swap(T& a, T& b) {
                    T tmp(std::move(a));
                    a = std::move(b);
                    b = std::move(tmp);
                  }
                  

                  我相信

                  1. std::swap(v,v) 保证没有影响,并且
                  2. std::swap 可以如上实现.
                  1. std::swap(v,v) is guaranteed to have no effects and
                  2. std::swap can be implemented as above.

                  以下引述在我看来暗示这些信念是相互矛盾的.

                  The following quote seems to me to imply that these beliefs are contradictory.

                  17.6.4.9 函数参数 [res.on.arguments]

                  1 以下每一项都适用于定义的函数的所有参数在 C++ 标准库中,除非另有明确说明.

                  1 Each of the following applies to all arguments to functions defined in the C++ standard library, unless explicitly stated otherwise.

                  ...

                  • 如果函数参数绑定到右值引用参数,则实现可能会假定此参数是对这个论点.[注意:如果参数是泛型参数表格 T&&并且绑定了类型 A 的左值,参数绑定到左值引用 (14.8.2.1) 因此不包括在前面的句子.— end note ] [ 注意:如果程序将左值转换为xvalue 同时将该左值传递给库函数(例如通过使用参数 move(x)) 调用函数,程序是有效地要求该函数将该左值视为临时值.该实现可以自由地优化掉别名检查如果参数是左值,则可能需要.——尾注]

                  (感谢 Howard Hinnant 提供报价)

                  v 成为从标准模板库中提取的某种可移动类型的对象,并考虑调用 std::swap(v, v).在上面的 a = std::move(b); 行中,T::operator=(T&& t) 的情况是 this == &b,所以参数不是唯一的引用.这违反了上述要求,因此当从 std::swap(v, v)a = std::move(b) 调用未定义的行为>.

                  Let v be an object of some movable type taken from the Standard Template Library and consider the call std::swap(v, v). In the line a = std::move(b); above, it is the case inside T::operator=(T&& t) that this == &b, so the parameter is not a unique reference. That is a violation of the requirement made above, so the line a = std::move(b) invokes undefined behavior when called from std::swap(v, v).

                  这里的解释是什么?

                  推荐答案

                  [res.on.arguments] 是关于客户端应该如何使用 std::lib 的声明.当客户端向 std::lib 函数发送 xvalue 时,客户端必须愿意假装 xvalue 确实是一个纯右值,并期望 std::lib 能够利用这一点.

                  [res.on.arguments] is a statement about how the client should use the std::lib. When the client sends an xvalue to a std::lib function, the client has to be willing to pretend that the xvalue is really a prvalue, and expect the std::lib to take advantage of that.

                  然而,当客户端调用 std::swap(x, x) 时,客户端不会向 std::lib 函数发送 xvalue.相反,它是这样做的实现.因此,责任在于使 std::swap(x, x) 工作的实现.

                  However when the client calls std::swap(x, x), the client isn't sending an xvalue to a std::lib function. It is the implementation that is doing so instead. And so the onus is on the implementation to make std::swap(x, x) work.

                  话虽如此,标准已经给了实现者一个保证:X 应该满足 MoveAssignable.即使处于移动状态,客户端也必须确保 X 是 MoveAssignable.此外,std::swap 的实现并不真正关心自移动赋值的作用,只要它不是 X 的未定义行为.即只要不崩溃.

                  That being said, the std has given the implementor a guarantee: X shall satisfy MoveAssignable. Even if in a moved-from state, the client must ensure that X is MoveAssignable. Furthermore, the implementation of std::swap doesn't really care what self-move-assignment does, as long as it is not undefined behavior for X. I.e. as long as it doesn't crash.

                  a = std::move(b);
                  

                  当 &a == &b 时,此赋值的源和目标都具有未指定(移动自)的值.这可以是空操作,也可以执行其他操作.只要它不崩溃,std::swap 就会正常工作.这是因为在下一行:

                  When &a == &b, both the source and target of this assignment have an unspecified (moved-from) value. This can be a no-op, or it can do something else. As long as it doesn't crash, std::swap will work correctly. This is because in the next line:

                  b = std::move(tmp);
                  

                  从前一行进入 a 的任何值都将从 tmp 获得一个新值.而tmp的原始值是a.所以除了消耗大量的 CPU 周期之外,swap(a, a) 是无操作的.

                  Whatever value went into a from the previous line is going to be given a new value from tmp. And tmp has the original value of a. So besides burning up a lot of cpu cycles, swap(a, a) is a no-op.

                  更新

                  最新工作草案,N4618 已被修改以明确说明在 MoveAssignable 要求中的表达式:

                  The latest working draft, N4618 has been modified to clearly state that in the MoveAssignable requirements the expression:

                  t = rv
                  

                  (其中rv 是一个右值),如果t,t 只需在赋值前等于rvrv 不引用同一个对象.无论如何,在赋值之后 rv 的状态是未指定的.还有一个额外的说明需要进一步说明:

                  (where rv is an rvalue), t need only be the equivalent value of rv prior to the assignment if t and rv do not reference the same object. And regardless, rv's state is unspecified after the assignment. There is an additional note for further clarification:

                  rv 仍然必须满足使用它的库组件的要求,无论 trv 是否引用同一个对象.

                  rv must still meet the requirements of the library component that is using it, whether or not t and rv refer to the same object.

                  这篇关于在移动赋值和移动构造函数方面实现 std::swap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                    • <small id='zRL7L'></small><noframes id='zRL7L'>

                        <tbody id='zRL7L'></tbody>

                      <tfoot id='zRL7L'></tfoot>

                      <legend id='zRL7L'><style id='zRL7L'><dir id='zRL7L'><q id='zRL7L'></q></dir></style></legend>

                        • <bdo id='zRL7L'></bdo><ul id='zRL7L'></ul>
                          <i id='zRL7L'><tr id='zRL7L'><dt id='zRL7L'><q id='zRL7L'><span id='zRL7L'><b id='zRL7L'><form id='zRL7L'><ins id='zRL7L'></ins><ul id='zRL7L'></ul><sub id='zRL7L'></sub></form><legend id='zRL7L'></legend><bdo id='zRL7L'><pre id='zRL7L'><center id='zRL7L'></center></pre></bdo></b><th id='zRL7L'></th></span></q></dt></tr></i><div id='zRL7L'><tfoot id='zRL7L'></tfoot><dl id='zRL7L'><fieldset id='zRL7L'></fieldset></dl></div>