質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
コンストラクタ

オブジェクト指向言語において、オブジェクトを生成時に呼び出され、データの初期化などを行なう関数・メソッドのことである。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1191閲覧

参照の初期化を条件分岐で行う方法について

nemumi-nomaki

総合スコア20

コンストラクタ

オブジェクト指向言語において、オブジェクトを生成時に呼び出され、データの初期化などを行なう関数・メソッドのことである。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/11/18 08:11

C++の参照の初期化を、コンストラクタで行うことに関する質問です。
コンストラクタで受け取った列挙体の値に応じて、参照に代入する値を変えたいと考えています。
そこで下のようなコードを書きました。

C++

1 2enum StoreType{ 3 Udon, 4 Gyudon, 5}; 6 7class Store { 8public: 9 Store(StoreType storeType); 10private: 11 Texture& texture; 12}; 13

C++

1Store::Store(StoreType storeType) 2{ 3 switch (storeType) { 4 case Udon: 5 texture = TextureAsset(L"Udon"); 6 break; 7 case Gyudon: 8 texture = TextureAsset(L"Gyudon"); 9 break; 10 } 11}

しかしこれでは、「参照が初期化されずに宣言されています」と出てコンパイルが通りません。
かといって、コンストラクタ初期化子では複雑な条件分岐を書くことが出来ません。
この場合、どのようにコードを書き換えればよいのでしょうか。このようなケースで参照を利用することは出来ますか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

std::reference_wrapperを利用しましょう、

投稿2018/11/18 08:22

yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nemumi-nomaki

2018/11/19 02:24 編集

回答ありがとうございました。 このTextureAssetはC++のゲームエンジンSiv3Dで提供されていたものです。 私自身、このTextureAssetはメモリ消費の大きいTextureをGlobalなtableから持ってくる関数で、参照でそれを持つことができれば軽量化が図れると考えていました。 しかし実際には、Textureは参照カウンタを持つハンドルであり、代入演算子 = やコピーコンストラクタでコピーした場合はメモリ消費は増えないとのことでした。 つまりこの場合はTextureそのものを実体として持つのが適当であるようです。 参考URL:http://siv3d.jp/bbs/patio.cgi?read=203 参照のラッパーが存在するのは知りませんでした。今回は上述の都合で用いませんでしたが、後学の為に覚えておきます。
guest

0

ベストアンサー

こんにちは。

例えば、TextureAsset(L"Udon")はどこに保持されますか?
仮に参照へ設定できてもTextureAsset(L"Udon")は一時オブジェクトですから、直ぐに不正参照になってしまいますよ。
この場合は、参照ではなく実体で保持するべきケースと思います。

投稿2018/11/18 12:50

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yumetodo

2018/11/18 13:41

名前的にglobalなtableから引っ張ってくる的なコードだと思っていたんですがそうでないならたしかにそう。
nemumi-nomaki

2018/11/19 02:14

回答ありがとうございました。 このTextureAssetはC++のゲームエンジンSiv3Dで提供されていたものです。 私自身、このTextureAssetはメモリ消費の大きいTextureをGlobalなtableから持ってくる関数で、参照でそれを持つことができれば軽量化が図れると考えていました。 しかし実際には、Textureは参照カウンタを持つハンドルであり、代入演算子 = やコピーコンストラクタでコピーした場合はメモリ消費は増えないとのことでした。 つまりこの場合はTextureそのものを実体として持つのが適当であるようです。 ご指摘ありがとうございました。 参考URL:http://siv3d.jp/bbs/patio.cgi?read=203
Chironian

2018/11/19 03:45

yumetodoさん あああ、確かにグローバルなテーブルから持ってくる可能性を見落としてました。 nemumi-nomakiさん なるほど、しかも本当にグローバルテーブルから持ってきていたのですね。 その際、参照カウンタを管理するからコンストラクタとデストラクタの呼び出しが必要だったということのようですね。この場合は、内部的にはポインタしか持ってなくても通常の変数として確保することでデストラクタが呼ばれるようになるので便利という流れのようです。 例えば、std::unique_ptrは内部的にはポインタを1つ保持しているだけですが、デストラクタ呼び出しをしたいので通常の変数として使います。 因みに参照カウンタ自体は管理される側のメモリに配置できる時はそうする場合が多いです。例えばstd::make_sharedのように。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問