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

“使用std::swap”如何启用ADL?

钱言
2023-03-14

在什么是复制交换习惯用法中,显示了这个例子:

friend void swap(dumb_array& first, dumb_array& second) // nothrow
{
    // enable ADL (not necessary in our case, but good practice)
    using std::swap; 

    // by swapping the members of two classes,
    // the two classes are effectively swapped
    swap(first.mSize, second.mSize); 
    swap(first.mArray, second.mArray);
}

使用std::交换究竟如何启用ADL?ADL只需要一个不合格的名称。我认为使用std::交换的唯一好处是,由于std::交换是一个函数模板,您可以在调用中使用模板参数列表(交换

如果不是这样,那么使用std::swap的目的是什么?


共有2个答案

邵伟
2023-03-14

“启用ADL”注释适用于

std::swap(first.mSize, second.mSize);
std::swap(first.mArray, second.mArray);

using std::swap;
swap(first.mSize, second.mSize);
swap(first.mArray, second.mArray);

您是对的,ADL只需要一个不合格的名称,但这就是重新处理代码以使用不合格名称的方式。

只是普通的

swap(first.mSize, second.mSize);
swap(first.mArray, second.mArray);

不起作用,因为对于许多类型,ADL找不到std::swap,并且范围内没有其他可用的swap实现。

蓝恩
2023-03-14

我只是想补充一下为什么要使用这个成语,这似乎是原始问题的精神所在。

这个习语在许多std库类中使用,在这些类中实现了交换。从http://www.cplusplus.com/reference/algorithm/swap/:

标准库的许多组件(在std中)以不合格的方式调用交换,以允许调用非基本类型的自定义重载,而不是这个泛型版本:在与类型相同的命名空间中声明的交换的自定义重载提供它们通过参数相关的查找选择这个泛型版本。

因此,使用非限定的“交换”来交换您描述的函数中的成员变量的目的是为了让ADL可以为这些类找到定制的交换函数(如果它们存在于其他地方)。

由于这些自定义类在您引用的类中不存在(在原始示例中,mSize和mArray分别是std::size\u t和int*),并且std::swap工作正常,因此作者添加了一条评论,指出在这种情况下这不是必需的,而是良好的实践。正如前面的回答所指出的那样,如果他明确地调用std::swap,他也会得到同样的结果。

为什么是良好实践?因为如果您有定义了自定义交换的类的成员实例,您希望其行为如下:检查自定义交换函数。。。如果存在,请使用它;如果不存在,请使用std库函数。如果没有可用的自定义交换函数,您希望它默认为上面链接中描述的简单std::swap实现。因此,“使用”,将内置类型的交换引入命名空间。但这些将在最后审判。

另请参见:https://stackoverflow.com/a/2684544/2012659

如果出于某种原因,您讨厌“使用std::swap”,我想您可以在理论上手动解决这个问题,方法是使用std::swap显式地调用std::swap来交换您想要交换的所有内容,并对定义的每个自定义交换使用非限定交换(仍然使用ADL)。但这很容易出错。。。如果您没有编写这些类,您可能不知道是否存在自定义的交换。在std::swap和swap之间切换会导致代码混乱。最好让编译器处理所有这些。

 类似资料:
  • 我想知道v1.swap(v2)使用std::交换(v1, v2)有什么好处。 从性能角度来看,我已经实现了一个简单的测试代码(我不确定它是否相关): 根据输出,向量::swap似乎在没有优化的情况下更快-O0。输出为(微秒): 与-O3没有显著差异。

  • 在我设法为我的类类型重载之后,我现在想要专门化它,而不是重载它,因为标准允许向名称空间添加模板专门化。下面是我的例子: 我不知道为什么它没有编译,并且我得到了一个错误:

  • 我在理解条件变量及其在互斥体中的使用时遇到了一些困难,我希望社区能帮助我。请注意,我来自win32背景,因此与CRITICAL_SECTION、HANDLE、SetEvent、WaitForMultipleObject等一起使用。 这是我第一次尝试使用C++11标准库进行并发操作,它是在这里找到的一个程序示例的修改版本。 关于这个的几个问题。 我读过“任何要等待std::condition_var

  • 是否有人有任何使用TBB有效并行std::分区的技巧?这已经完成了吗? 以下是我的想法: 如果数组很小,std::将其分区(串行)并返回 否则,使用自定义迭代器将数组视为2个交错数组(在缓存大小的块中交错) 为每对迭代器启动一个并行分区任务(递归到步骤1) 在两个分区/中间指针之间交换元素* 返回合并的分区/中间指针 *我希望在一般情况下,与数组的长度相比,或者与将数组划分为连续块时所需的交换相比

  • 在我的Fedora 34环境(g)中,定义为: 如果表达式已经是右值,那么

  • 问题内容: 我已经看到了很多类似的问题,但是还没有找到解决我特定问题的方法。我正在尝试SWIGify一些使用std :: function的C ++ 11代码,因此可以在Java应用程序中使用它。 我遇到了这样的共享指针: 并使用shared_ptr指令成功处理了它们,如下所示: 我遇到了像这样的共享指针向量: 并使用如下模板成功处理了它们: 现在我有一个这样的方法: 而且我无法让SWIG正确包装