変数定義でのconstと&の意味


uehara  2008-02-15 01:16:23  No: 67498

以下の様なクラスがあります。

class cTransFile
{
  // member
  std::string mStorageDir;
  std::string mIndexFile;
}

以下の定義文があります。

cTransFile mTransA;
cTransFile & mTransB;
const cTransFile & mTransC;

この際、mTransA、mTransB、mTransC  では、
それぞれどのような違いが生まれてくるのでしょうか。

今まで  mTransA  の様な定義しか使った事が無く、
const を使用した場合、&を使用した場合等で、
何が変わるのかがわかりません。
(internet上でも検索してみましたが、"&"で検索しても見当違いのものがヒットするばかりで・・・)

よろしくお願いいたします。


tetrapod  2008-02-15 01:27:06  No: 67499

& は C++ の文法で「参照」と呼ばれるものだ
掲示板のスペースで「参照とは何ぞや」を説明できるとは思えないので、自分で調べてみよう

> cTransFile & mTransB;
> const cTransFile & mTransC;
参照は「参照だけ単体では」使えない約束になっているのでこれはヘン
初期化子を明示的に伴うか、関数の仮引数である(がゆえに暗黙に初期化子を伴う)か、
どっちかになっているはずだ


uehara  2008-02-15 02:50:06  No: 67500

回答ありがとうございます。

> 参照は「参照だけ単体では」使えない約束になっているのでこれはヘン
ヘンと言うのは「問題のある構文である」と言う意味でしょうか。
上記で記したソースコードは、既に完成されたモジュール内のコードであり、
コンパイルエラー等は発生していないそうです。
(手元に実行環境とソースが存在しないので詳細は不明)

> 初期化子を明示的に伴うか、関数の仮引数である(がゆえに暗黙に初期化子を伴う)か、
> どっちかになっているはずだ
意味がよくわかりません。
& が存在する時、cTransFile 内で変数定義時に初期値として渡された値が継承される。
const が付くと、cTransFile 内で変数定義時に初期値として渡された値が継承され、その値の変更は不可。
との予測を建てたのですが、手元でそれを実証することが出来ず困っています。


tetrapod  2008-02-15 03:48:21  No: 67501

単純に訊きまくるよりも少しは自分で調べたり試したりしようぜ
そのうえでまだ判らない・疑問があれば、そこで初めて掲示板で訊いてくれ

> ヘンと言うのは「問題のある構文である」と言う意味でしょうか。
少なくとも以下のソースコード断片はコンパイルできない。できたらコンパイラのバグ。
int funcNG() { int& r; return r; }

以下のコードならコンパイルできるし、プログラマの意図どおりに動く
int funcOK1(int& r) { return r; }
int funcOK2() { int x=0; int& r=x; return r; }

参照はポインタと似てるが「参照する何かが絶対に必要」という点で異なる。
const 参照を経由して、参照元を書き換えることはできない、というあたりはポインタと同等


通りすがり  2008-02-15 03:51:27  No: 67502

詳細は不明とかいってないで
class cTransFile
{
// member
std::string mStorageDir;
std::string mIndexFile;
};

cTransFile mTransA;
cTransFile & mTransB;
const cTransFile & mTransC;
手元でをビルドしてみればいいじゃん
ビルド通らないから


wclrp ( 'o')  2008-02-15 04:14:09  No: 67503

『値が継承』ってどういう意味なのかわかりません。

参照は変数に別名を付けたような効果があるよ。
cTransFile mTransA;
cTransFile & mTransB = mTransA;
とした場合、
mTransB.mStorageDirは、mTransA.mStorageDirと同一のものを指している。

constは参照じゃなくても付けることができるので
参照とは別に理解すればいいと思う。

おそらくこういうことだろう

class cTransFile
{
public:
  cTransFile() { }
  std::string mStorageDir;
  std::string mIndexFile;
};

class X {
public:
  cTransFile mTransA;
  cTransFile & mTransB;
  const cTransFile & mTransC;
  X();
};

X::X()
: mTransB = mTransA
, mTransC = mTransA
{
}

というのも、参照型とconstは途中で値を変えることができないから
コンストラクタで設定するはず。

上記はコンパイル確認していないのでエラーになるかもしれませんけど。
説明の都合によりpublic:を付けました。

メンバ変数とういう意味でmを付けているのかもしれないが
回答者には全体像が見えないので回答に難儀する。

constは値の変更禁止だから以下のようになるはず
mTransB.mStorageDir = "a"; // コンパイルok
mTransB.erase(); // コンパイルok
mTransC.mStorageDir = "a"; // コンパイルエラー
mTransC.erase(); // コンパイルエラー
これも動作確認していないのでミスがあるかも。


wclrp ( 'o')  2008-02-15 04:18:25  No: 67504

以下のように書くつもりだった。
mTransB.mStorageDir = "a";
mTransB.mStorageDir.erase();
mTransC.mStorageDir = "a";
mTransC.mStorageDir.erase();

単純に
int a = 1;
const int c = 2;
a = 3;
c = 4;
の方がわかりやすいか。


そだ  2008-02-15 08:42:54  No: 67505

>上記で記したソースコードは、既に完成されたモジュール内のコードであり、
>コンパイルエラー等は発生していないそうです。
>(手元に実行環境とソースが存在しないので詳細は不明)

名前の付け方といい意味のなさといい
実用的なモジュールを作る上であのコードが
そのままソースに書かれるのはありえないような・・・
っていうツッコミはだめですかねぇ。

文法理解しているか試すための
なんかの試験問題じゃないんでしょうか。

>& が存在する時、cTransFile 内で変数定義時に初期値として渡された値が継承される。
>const が付くと、cTransFile 内で変数定義時に初期値として渡された値が継承され、その値の変更は不可。

wclrp ( 'o')  さんがちょろっと触れましたが、コード見る限り
「変数定義時に初期値として渡された値」がないですよね。あるはずがないです。

少なくともメンバ変数を宣言するときに初期値は設定できなかったはず。
なのでコンストラクタ関数内で初期値を代入するのが初歩的な初期化方法だった気がします。

下の2行の引用をそのまま解釈して書いた
class A {
    int b = 32;
};
みたいな宣言は純仮想関数の宣言とかの例外を除いてコンパイルエラーだったと思います。


yoh2  2008-02-15 09:08:06  No: 67506

細かいツッコミですが、

> X::X()
>  : mTransB = mTransA
>  , mTransC = mTransA
>  {
>  }

正しくはこうですね。

X::X()
 : mTransB(mTransA)
 , mTransC(mTransA)
 {
 }


通行人  2008-02-15 18:58:23  No: 67507

// hoge.h
class hoge
{
private:
    cTransFile & mTransB;
};

// hoge.cpp
hoge::hoge() : mTransB( /*何か*/ )
{
}

みたいな感じでヘッダーしか見てないから
コンパイルも通ってて何してるかわからんってことかな?


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加