swapが心の友なのは特に C++ だ。
こんな:
1 struct myclass_impl; // opaque, implementation's detail
2
3 class myclass { // final, thus we don't have virtual
4 friend struct myclass_impl;
5
6 myclass_impl* impl;
7 public:
8 explicit myclass();
9 myclass(const myclass& other);
10 myclass& operator=(const myclass& rhs);
11 ~myclass();
12
13 // ...省略...
14 };
15 // ...省略...
1 struct myclass_impl {
2 // ...省略...
3 };
4
5 myclass::myclass()
6 : impl(new myclass_impl())
7 {
8 }
9 myclass::myclass(const myclass& other)
10 : impl(new myclass_impl(*other.impl))
11 {
12 }
13 myclass& myclass::operator=(const myclass& rhs)
14 {
15 myclass tmp(rhs); // duplicate impl from rhs to tmp
16 // take impl of tmp (originally duplicated from rhs) to this.impl
17 std::swap(this->impl, tmp.impl);
18 //tmp dtor -> delete impl originally owned by this.
19 return *this;
20 }
21 myclass::~myclass()
22 {
23 delete impl;
24 }
25 // ...省略...
この swap の活用方法がどんな理由で「優れている」のかについては、とにかく以下で「楽しく」読める:
More Exceptional C さらに40のクイズ形式によるプログラム問題と解法 (C In‐Depth Series) |
既にかなり古い本になってしまっているため、C++11 しか知らないような人はちょっと注意はした方が良いけれど、ただ、これはもはや「古典」とも言うべき名著。是非手にとってみて欲しい。
読んでる暇がない、という人のためにはポイントだけ。一に、「例外安全」。二に、「効率」。「ポインタを交換する」ことは、限りなくゼロオーバヘッドで、かつ、例外を起こさない「アトミックな」操作であるという点がポイント。であるから、STL の全てのコンテナに swap が提供されている。
で、まぁ「ポインタの swap」でなくても swap なんかは多用はするわけなんだけれども、ただ、それを理由に「心の友よ」とまでは言えんでしょう。なくても「面倒」なだけだから致命傷ではないし、ないなら書けばいいだけ、程度の話。生の C しかなかった頃は標準の swap なんかなかったので、皆自分でマクロを書いてたわけで。
さて。これ書いたときにふと、「はて、python で swap ってどう書くんだっけな?」が頭をよぎった、と書いた。これ、一般解は実に簡単なことであったわ:
1 a = 1
2 b = 2
3
4 a, b = b, a
基本 Python 脳には慣れてるつもりではあるんだけれど、C++ 脳も抜けないもんで、こういう FAQ 的なことも割とよく忘れるの…。あ、FAQ もたまに読んだ方がいーよ、アタシのようにバカにならないように。