int i;とint(i);が違う挙動になるケース


の続きです。色々試していて違いがある場合があったので記録。

というかまだC++の基礎学習してる最中なのに何だか変に深いところまで覗き込んでしまった気がしますorz

さて、変数宣言におけるint i;とint(i);に違いはまったくないことは分かりました。

なので以下のように書くとコンパイルエラーになります。

int main () {
    int i;
    int(i);
    
    return 0;
}
$ cl /W4 /EHsc main.cpp
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(6) : error C2086: 'int i' : 再定義されました。
        main.cpp(5) : 'i' の宣言を確認してください。

iという変数はすでに定義されているため、同じ名前のi変数を定義できないというエラーですね。

int i;とint(i);が等価なので当然のエラーです。

しかし、以下のように書くとエラーにならずにコンパイルが通ってしまいます。

#include <iostream>
using namespace std;

int main () {
    int(i) = 100;
    int j = int(i);
    
    cout << j << endl;
    
    return 0;
}
$ main
100

同じint(i);でも、書く場所によって動作が変わるようです。

int(i);を左辺値に置いた場合は変数宣言になりますが、右辺値に置いた場合は型キャストなるようです。

またクラス型の場合も同じで、左辺値なら変数宣言になり、右辺値なら前回勉強したRVOになります。

ちなみにint i;を右辺値に置いた場合はどうなるでしょうか?

試してみます。

#include <iostream>
using namespace std;

int main () {
    int i = 100;
    int j = int i;
    
    cout << j << endl;
    
    return 0;
}
$ cl /W4 /EHsc main.cpp
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(7) : error C2062: 型 'int' は不要です。

何か良く分からないエラーがでました。やはり予想通りint i;は右辺値には置けないようです。

まとめます。

  • int i;とint(i);は左辺値に置いた場合は変数宣言となり、完全に等価。
  • int(i);を右辺値に置いた場合はキャストになる(クラスの場合はRVOになる)
  • int i;を右辺値に置いた場合コンパイルエラーとなる。


と、ここまで書いてて凄いことを思い出しました。

以前vectorのswap技法について学んだときにこういうものがありました。

そこで中身のデータは残したまま領域の切りつめを方法として名前のないオブジェクトを利用するという方法があります。

// 名前のないオブジェクトのコンストラクタにarrayを渡す
vector<int> (array).swap(array);

これで中身のデータを保持しつつ切りつめができました。

ちなみにこの名前のないオブジェクトについてはまだよくわかってないのでまた調べる必要がありますね。

vectorで確保した領域の切り詰め(swap技法) - (void*)Pないと

当時これの意味がまったく分かってませんでしたが、これは「vector(array)」だけを見れば左辺値によるarray変数の宣言にも見えますが、「.swap」のようにswap関数を続けて呼び出すことで右辺値と認識され、既に定義されているarrayとの再定義エラーにならずに、arrayをコンストラクタの引数に取るRVOのオブジェクトとして次のswapを呼んでいたという感じだったんじゃないでしょうか。

言葉尻は若干間違えてるかもしれませんが(特に左辺値右辺値RVOあたり)、イメージはあってそうな気がします。