C++の参照型について

こちらを参考にしました。

参照型とは

変数に別名をつけて参照することが可能となるC++の機能

int x = 20;
int& y = x; // yをint型への参照として定義。参照先:x
y = 30; // xも30となる。

参照型を宣言するためには、宣言の前に&をつける。 アドレス演算子&とは異なることに注意。

ポインタと参照型

ポインタと参照型は類似しているが、微妙に異なる。 差異としては、 * ポインタは宣言後の代入が可能だが、参照型は宣言と代入は一体(参照先は変更不可)  (ポインタはアドレスを指すが、参照は変数のアドレスを指すようなもの。)

参照型を定義するときは、初期化も一緒にする必要がある。

int x;
int& y;
y = x; // コンパイルエラー!!!

上記の性質により、参照型は指し先があいまいになったり、nullptrを指したりすることはない。

セマンティクスとシンタックス

こちらの記事を参考にいたしました。

セマンティクスとシンタックス

セマンティクスとは、意味論を表し、シンタックス構文を表す。

つまり シンタックス: 目的の動作を達成するプログラムを、どのように記載するかというルール セマンティクス: ソースコードがどのような意味をもっているか

言い換えると、 - シンタックス: ソースコードをどう描くか - セマンティクス:ソースコードはどう動くか

例えば、C言語において、

int a[4];

a[4] = 1;

と、

*(a + 4) = 1;

これらは、異なるシンタックスを用いてるが、同じセマンティクスとなる。

auto_ptrの非推奨理由

参考にした記事によると、C++11からauto_ptrが非推奨となった理由は、 =を用いたシンタックスは通常コピーを表すにも関わらず、auto_ptrを用いた場合のみ、 moveのセマンティクスを持った動作をしていた。

C++11で定義されたunique_ptrでは、そもそもコピー=が禁止となった。

右辺値と右辺値参照

こちらの記事を参考にいたしました。

右辺値と左辺値の違い

C++では、右辺値と左辺値が明確に区別される。

int i = 1;

例えば、上記ではiが左辺値, 1が右辺値となる。 左辺値は、名前付きオブジェクトであり、右辺値はすぐに破棄されるもの。 右辺値として、コンストラクタや関数の戻り値などがある。

右辺値は、基本的に評価された時点で破棄される。 そのため、左辺値を定義しないコンストラクタの戻り値は、関数を抜ける前に破棄される。

class something{
 public:
  ~something() {
    printf("something destructor");
 };
}


int main ()
{
   something();  // この時点でprintされる(関数抜ける前に!!)
  printf("after something")
  return 0;
}

実行結果は以下のようになる

something destructor
after something

一方で、Object aのような名前付きオブジェクトを左辺値という。 左辺値はスコープを抜けるまで破棄されない。

右辺値参照

右辺値のスコープをのばすには、右辺値参照というものを用いる。

int&& a = 10;

右辺値参照型はT&&で定義できる。 右辺値参照型は左辺値のため、右辺値は、スコープを抜けるまで破棄されないことになる。

左辺値を右辺値にキャストする

std::moveを用いると、左辺値を右辺値にキャストできる。 これがムーブセマンティクスを表現するシンタックスのひとつとなる。

これは、値のコピーをしたくない場合に、所有権を奪うときに使用したりする。