このブログは、旧・はてなダイアリー「檜山正幸のキマイラ飼育記 メモ編」(http://d.hatena.ne.jp/m-hiyama-memo/)のデータを移行・保存したものであり、今後(2019年1月以降)更新の予定はありません。

今後の更新は、新しいブログ http://m-hiyama-memo.hatenablog.com/ で行います。

爺感:ドカンと代入したり戻したり

ジイサマ(=自分)の感覚だと、Cの代入演算子 = でセットできるのは単純な型だ、という先入観がある。s = "abc"; はstrcpy()やstrdup()とは違う。if (s == t) のように文字列を比較してもしょうがない、strcmp() 使え、ってことになる。

ところが、最近だと演算子オーバーロードが出来るので、デカくて複雑なデータでも、= でコピーして == で比較ができる。= がstcpy()のように使える、ってのがどうも馴染めない。

同じ感覚だと思うが、

std::string foo() {
  std::string s;
  // ...
  return s;
}

も、一瞬ヒヤッとする。これもオブジェクト自体が戻るんで大丈夫なんだけど、「オブジェクト自体が戻る」ってのが馴染めない、慣れない。昔のコンパイラって、引数に載せるのも戻り値で返せるのも、intサイズだったかlongサイズだったか、ともかく整数レベルだったと思う。

要するに、爺感では、次のものは「整数サイズ」に限定されるのだ。

  • 引数
  • 戻り値
  • = での代入
  • == で比較できる。

最近は違うわけだよ。

#include <iostream>

struct foo {
    int foo_1;
    long foo_2;

    foo() {
        foo_1 = 0;
        foo_2 = 0;
    }
};

std::ostream& operator<<(std::ostream& os, const foo& x)
{
    os<< "[" << x.foo_1 << ", " << x.foo_2 << "]";
    return os;
}

foo make_foo() {
    foo x;
    return x;
}

foo inc_foo(foo x) {
    x.foo_1 += 1;
    x.foo_2 += 1;
    return x;
}

foo& inc_foo_ref(foo& x, int y = 1) {
    x.foo_1 += y;
    x.foo_2 += y;
    return x;
}

int main()
{
    foo x1 = make_foo();
    std::cout << "x1=" << x1 << std::endl << std::endl;
    foo x2 = inc_foo(x1);
    std::cout << "x2=" << x2 << std::endl;
    std::cout << "x1=" << x1 << std::endl << std::endl;
    foo& x3 = inc_foo_ref(x1, 2);
    std::cout << "x3=" << x3 << std::endl;
    std::cout << "x2=" << x2 << std::endl;
    std::cout << "x1=" << x1 << std::endl << std::endl;
    inc_foo_ref(x1, 3);
    std::cout << "x3=" << x3 << std::endl;
    std::cout << "x2=" << x2 << std::endl;
    std::cout << "x1=" << x1 << std::endl << std::endl;
    return 0;
}

ウーム。