想问一下 https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom/3279550#3279550 这个链接里的这个下面这段 public: friend 是怎么理解的呢? po 主尽力看了原回答给的链接,有些没有看懂。
class dumb_array
{
public:
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 objects,
// the two objects are effectively swapped
swap(first.mSize, second.mSize);
swap(first.mArray, second.mArray);
}
};
1
ysc3839 2019-09-12 23:27:26 +08:00 via Android
因为 mSize 和 mArray 是 private 的,所以需要声明成 friend 才能访问。
|
3
Tony042 2019-09-13 00:01:29 +08:00
同意楼上的,另外 friend 声明写在 public 上面吧,还有 declaration 和 definition 最好分开写,写在一起很乱
|
4
alanlian OP @Tony042 emm 这个只是一个小 sample,是我给的链接里的回答者拿来说明 copy-and-swap idiom 这个问题的,他好像是特意把 friend 写在那个位置的?可以看一下我给的链接
|
7
alanlian OP @ysc3839 可以看下我给的链接,在 A successful solution 这一节,我是直接 copy 里面的代码的
|
8
secondwtq 2019-09-13 01:15:56 +08:00
friend 好像是只能写在这吧 ...
这里 swap 是个成员函数,成员函数是可以不加 friend 访问自己的 private 成员的 之前好像没见过这么写 copy-and-swap idiom 的(不过 C++11 之后好像不用这个 idiom 也可以了 |
9
secondwtq 2019-09-13 01:24:00 +08:00
啊等等我好像搞混了,无视掉 #8 的评论吧 ... 我再看看
|
10
cyyzero 2019-09-13 01:57:39 +08:00 via Android 1
没有 friend 就是成员函数了啊
|
11
tianshilei1992 2019-09-13 07:40:25 +08:00
那段代码应该这样写才是直观的:
class dumb_array { public: friend void swap(dumb_array& first, dumb_array& second); }; void swap(dumb_array& first, dumb_array& second) { ... } 类里面的那个函数是“声明”,下面的那一段才是真正的“定义”。因为在函数的实现里面用到了类的私有成员,因此就必须得将这个函数在类里面声明成 friend 才可以。 |
12
ysc3839 2019-09-13 08:44:47 +08:00 via Android
@alanlian 我要的是你的“我去掉 friend 还是可以编译成功”的代码。链接中的代码是有 firend 的。
|
13
alanlian OP @ysc3839 https://paste.ubuntu.com/p/C9bNY8XBJV/ 大约是这样的,你看有什么问题麽?
|
15
alanlian OP @tianshilei1992 但是为什么不可以直接作为一个成员函数呢?
|
16
ysc3839 2019-09-13 11:01:34 +08:00 via Android 1
@alanlian 因为没有在类外部调用 swap,所以没问题吧。
代码中给出的用法是 std::swap 这样单独一个函数的 https://en.cppreference.com/w/cpp/algorithm/swap 你不写 friend 的话就变成类中的函数了,要使用的话会变成 a.swap(a, b) 这种样子。 |
17
namehao 2019-09-13 11:39:53 +08:00 2
不加 friend 是可以编译成功的,这样的 swap 是类的一个成员函数,对于 operator=这样的操作也是没有问题的。
但是对于如果在类的外部调写这样的代码。比如在 main 函数中写:dumb_array a, b; std::swap(a, b);那么在 c++11 中是 c=move(a),a = move(b), b = move(c)这样的操作,因为 dumb_array 没有写移动构造和移动赋值函数,就导致会调用拷贝构造函数。 这样导致的问题就是,swap 本来可以直接将类内的数组指针值进行替换,却多构造了一个临时数组,来进行换值操作。 当把 swap()写成 friend 之后,swap 就成了 std::swap()的一个重载函数,当在 main 中进行 std::swap(a,b)调用的时候,调用到的就是作为 friend 函数的 swap,也就是 std::swap()的定制版。这样就是直接将类内的指针进行交换,而不用进行额外的拷贝构造函数的调用。 不知这样,讲明白了没有。 |
21
secondwtq 2019-09-13 15:31:00 +08:00 via iPad
这个不是重载的 std::swap,这个新函数应该是通过 ADL 被找到的
|
22
alanlian OP @secondwtq https://stackoverflow.com/questions/11562/how-to-overload-stdswap 这个链接里的这个巨巨也是用的 overload 这个词呢?您看下
|
23
secondwtq 2019-09-13 17:18:04 +08:00 1
@alanlian 意思类似于:
Q:传输大文件用什么服务最吼? A:顺丰快递 你感受一下 标准对 overload 的定义:“When two or more different declarations are specified for a single name **in the same scope**, that name is said to be overloaded.” technically,你在使用 swap 的时候用了 overload resolution 的机制,overload resolution 在决定 candidate set 的时候会考虑 scope 和 ADL。不过 overload resolution 和 overloading 是两回事 |
25
secondwtq 2019-09-13 17:37:23 +08:00
其实应该说,你正确调用 swap 的时候,把 std::swap 重载了
另外 C++20 之前调 std::swap 应该是不会调到你的 swap 去的 |
26
baixiangcpp 2019-09-13 17:38:27 +08:00
《 EFFective C++》肯定没好好看
|
27
baixiangcpp 2019-09-13 17:41:00 +08:00
接上条,没写完就发了) 里边专门有个条款,就讲了 swap,虽然《 C++ primer 》也提过一嘴,但是一笔带过了.....
|