公共朋友交换成员函数
|
在对复制和交换惯用语的漂亮回答中,有一段代码需要一些帮助:
class dumb_array
{
public:
// ...
friend void swap(dumb_array& first, dumb_array& second) // nothrow
{
using std::swap;
swap(first.mSize, second.mSize);
swap(first.mArray, second.mArray);
}
// ...
};
然后他加了一张纸条
还有其他主张,我们应该针对我们的类型专门使用std :: swap,在提供免费交换功能的同时提供类内交换,等等。但这都是不必要的:对交换的任何正确使用都将通过不合格的调用,我们的功能将通过ADL找到。一种功能将起作用。
我必须承认,对于“ 1”,我对“不友好”的说法有些不满。因此,我的主要问题是:
看起来像一个自由函数,但是它在类体内?
为什么swap
不是静态的?它显然不使用任何成员变量。
\“任何正确使用交换的方法都可以通过ADL找出交换” \“? ADL将搜索名称空间,对吗?但是它也可以在类内部查看吗?还是这里出现friend
?
附带问题:
使用C ++ 11,我应该用ѭ5标记我的swap
吗?
使用C ++ 11及其range-for,我应该在类中以相同的方式放置friend iter begin()
和friend iter end()
吗?我认为这里不需要friend
,对吗?
没有找到相关结果
已邀请:
2 个回复
薄响
的写法有几种,有些比其他的要好。但是,随着时间的流逝,发现单个定义最有效。让我们考虑一下如何考虑编写writing2ѭ函数。 我们首先看到像
这样的容器具有一个单参数成员函数
,例如:
那么,我们的班级自然也应该吧?好吧,不是真的。标准库包含各种不必要的东西,成员
是其中之一。为什么?我们继续。 我们应该做的是确定什么是规范的,以及班级需要做什么才能使用它。交换的标准方法是
。这就是为什么成员函数没用的原因:它们通常不是我们应该如何交换事物的方式,并且与
的行为无关。 那么,为了使
工作,我们应该提供and15ѭ的专业知识(对
应该提供),对吗?
在这种情况下,这当然可以工作,但是存在一个明显的问题:功能专长不能是部分的。也就是说,我们不能仅使用特定的实例来专门化模板类:
此方法在某些时间有效,但并非所有时间都有效。肯定有更好的办法。 有!我们可以使用
函数,并通过ADL找到它:
当我们想交换东西时,我们关联†15,然后进行不合格的通话:
什么是“ 1”功能?这个区域周围有混乱。 在C ++标准化之前,“ 1”函数进行了一些称为“朋友名称注入”的操作,其中代码的行为就好像该函数是在周围的命名空间中编写的。例如,这些是等效的预标准:
但是,当发明了ADL时,将其删除。然后只能通过ADL找到
函数。如果您希望将其作为自由函数,则需要这样声明它(例如,参见此内容)。但是!出现问题了。 如果仅使用
,就永远不会发现您的过载,因为您已经明确地说“请看
,而没有其他地方”!这就是为什么有人建议编写两个函数的原因:一个是通过ADL找到的函数,另一个是处理显式的“ 32”资格的函数。 但是就像我们看到的那样,这并非在所有情况下都有效,并且最终导致丑陋的混乱。取而代之的是,惯用的交换走了另一条路:不是让类提供job15的工作,而是让交换者确保他们不使用合格的ѭ2的工作,就像上面一样。只要人们知道这一点,它就可以很好地工作。但是这里存在问题:需要使用不合格的呼叫是不直观的! 为了简化操作,像Boost这样的某些库提供了函数
,该函数只对just2ѭ进行了无限定的调用,并以
作为关联的命名空间。这有助于使事情再次变得简洁,但仍然令人沮丧。 请注意,C ++ 11中的
行为没有变化,我和其他人错误地认为是这种情况。如果您对此有所了解,请在此处阅读。 简而言之:成员函数仅仅是噪声,专业化是丑陋且不完整的,而
函数却是完整且有效的。交换时,请使用
或不合格的
并关联
。 †非正式地,如果在函数调用期间要考虑名称,则将其关联。有关详细信息,请参阅第3.4.2节。在这种情况下,通常不考虑ѭ15。但是我们可以将其关联(将其添加到不合格的
考虑的重载集合中),以便找到它。
厘恼轨
在类内定义的一个朋友函数是: 放在封闭的名称空间中 自动
无需进一步资格即可提及班级的静态成员 确切的规则在第ѭ47节中(我引用了C ++ 0x草案的第6和第7段): 当且仅当该类是非本地类(9.8),函数名称不合格且该函数具有名称空间范围时,才可以在该类的朋友声明中定义一个函数。 此类函数是隐式内联的。在类中定义的朋友功能在其定义的类的(词法)范围内。在类外部定义的朋友函数不是。