首页 > 解决方案 > 通常实现 std::swap 重载的基本原理

问题描述

让我们考虑以下最小代码示例:

// Dummy struct
struct S
{
    int a;
    char * b;

    // Ctors, etc...
};

void swap(S & lhs, S & rhs)
{
    using std::swap;

    swap(lhs.a, rhs.a);
    swap(lhs.b, rhs.b);
}

语境

我知道当我们打算调用一个swap()函数时,正确且推荐的方法是执行以下操作:

// Let's assume we want to swap two S instances.
using std::swap;
swap(s1, s2);

这样,如果有(在给定类型命名空间中定义),ADL 能够找到适当的重载,否则std::swap使用。

然后我读了一些SO线程:

使用相同的习惯用法(即使对于内置或指针类型),但不仅在我们调用重载时,std::swap()而且在我们定义它时。

问题

如果成员都是内置类型(或指针类型,可能是指向自定义类型的指针),是否仍然需要/建议使用该习惯用法而不是显式调用std::swap()

例如,考虑到我提供的小代码示例,因为S成员是内置类型,是否可以(格式良好)将其定义如下:

void swap(S & lhs, S & rhs)
{
    std::swap(lhs.a, rhs.a);
    std::swap(lhs.b, rhs.b);
}

或者也许有一个我看不到的原因仍然需要使用这种using std::swap;方式?

标签: c++language-lawyerswap

解决方案


由于 S 成员是内置类型,是否可以将其定义如下(格式正确):[std::swap 用法]

是的。我的意思是,它之所以有效,是因为如果它们都是andstd::swap ,则只需“交换值 a 和 b” ,即内置类型。MoveAssignableMoveConstructible

如果成员都是内置类型(或指针类型,可能是指向自定义类型的指针),是否仍然有必要/建议使用该习惯用法而不是显式调用 std::swap() ?

只是为了你类的未来:如果有一天它的任何成员被用户定义的类型替换,你可能会忘记修改你的swap并错过一个“专门的”ADL 实现,仍然调用std::swap可以(理论上)的泛型效率低下但仍然编译。

boost::swap实际上,如果您总是自己使用或实现它,您甚至不需要考虑它:

template<typename T> void swap(T& a, T& b) {
    using std::swap;
    swap(a, b);
}

推荐阅读