0%

代码展示

先在参数的位置创建一个新的对象,然后和 *this 交换。

struct MyClass {
    MyClass& operator=(MyClass other) {
        swap(*this, other);
        return *this;
    }

    friend void swap(MyClass &a, MyClass &b) noexcept; {
        using std::swap;
        swap(a.member1, b.member1);
        swap(a.member2, b.member2);
    }

    int member1;
    int member2;
};

这种实现既能够匹配 const MyClass & 的情况,又能匹配 MyClass && 的情况,而且代码行数更短。

注意点 1:必须自定义 swap 函数

使用这种写法必须提供我们自己的 swap 函数,因为 std::swap 对一般类型的实现是使用了构造的,如果不提供我们自己的 swap 函数而去直接调用 std::swap,就会无限递归!std::swap 的相关代码如下:

    void
#endif
    swap(_Tp& __a, _Tp& __b)
    _GLIBCXX_NOEXCEPT_IF(__and_<is_nothrow_move_constructible<_Tp>,
				is_nothrow_move_assignable<_Tp>>::value)
    {
#if __cplusplus < 201103L
      // concept requirements
      __glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
#endif
      _Tp __tmp = _GLIBCXX_MOVE(__a);
      __a = _GLIBCXX_MOVE(__b);
      __b = _GLIBCXX_MOVE(__tmp);
    }

参考 https://itanium-cxx-abi.github.io/cxx-abi/abi.html#member-pointers

向下转换的能力!

和类的指针/引用的转换不同,指向成员的指针既可以向下转,又可以向上转!只需要目的类型拥有对应的成员即可。

struct A    { long a; };
struct B: A { long b; };
int main() {
    // long (A::*p) = &B::b; // 错误,A 类型没有成员 B::b
        long (A::*q) = &B::a; // B::a 和 A::a 是相同的
    long (B::*r) = &A::a; // 向下转
}

指向数据成员

需要存储 this 偏置,按照 Itanium C++ ABI,存储的类型为 ptrdiff_t。一般数据成员指针就用其相对于开头的偏移作为指针的值,而空指针则用 -1 表示。

奇怪的现象:对指向数据成员指针的空初始化会将其置为空指针,也就是 -1虽然含义为空,但是其比特位并不是全零的。

这个写的时间比较早了,当时有的问题现在可能已经被弥补了。

bcdedit 和 hypervisor 相关,直接关掉 hypervisor 还不能够完全关闭。一些软件仍然不能够运行。

运行 bcdedit /set hypervisorlaunchtype off(需要管理员权限)后再重启可以关掉这个功能。直接使用 bcdedit 开始查看当前的配置状况。