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

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

新規登録して質問してみよう
ただいま回答率
85.53%
C++

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

Q&A

解決済

2回答

18191閲覧

C++のシングルトンを関数内静的変数として確保するのが正しい理由

yuba

総合スコア5568

C++

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

0グッド

2クリップ

投稿2015/10/07 02:52

WikipediaやMore C++ Idiomsでも紹介されている、シングルトンインスタンスの確保の仕方

C++

1class Singleton { 2 // 各種コンストラクタを外部から呼べなくするあれこれ 3 : 4 5 // インスタンスの取得メソッド 6 static Singleton& getInstance(){ 7 static Singleton inst; 8 return inst; 9 } 10 11 // 以下実装 12 : 13}

ですが、このクラスをヘッダファイルで宣言した場合にSingleton::getInstance() が唯一オブジェクトを返してくれる理由が今ひとつ理解できていません。

このファイルを Singleton.h と名付けたとして、複数のcppファイルからこのヘッダをインクルードした場合、各cppファイルで別々にこのヘッダが展開され、別々にこのクラスを認識し、getInstance関数も定義されたことになるので、各cppファイル毎に別のインスタンスを見てしまうのでは? と疑問に思うわけです。

どう理解すべきでしょうか。

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

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

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

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

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

guest

回答2

0

複数のcppからインクルードされるヘッダでの定義が多重定義にならないのか?という疑問は深いです。
私自身、長年曖昧なままにしていたので、ヘッダのインクルードでいつも無駄な苦労をしてました。
そこで、少し異なる視点から回答させて下さい。

①関数の中で定義されたstatic変数は、関数の定義毎に1つ領域が確保されます。
②同じ関数の定義はプログラム全体で1つだけしか許されません。

従って、ご提示されたSingleton::getInstance()関数の定義は1つしか存在できず、その中で定義されたstatic変数も1つだけ領域が確保されます。
ですので、Singleton::getInstance()が返すinstはみな同じものになります。

複数のcppファイルからこのヘッダをインクルードした場合

(後略)

「同じ関数の定義は1つしか許されないのに、複数のcppからインクルードされるヘッダで定義すると多重定義されることにならないか?」という疑問に帰着すると思います。

yohhoyさんが参照されているように、クラス定義の中で直接定義されたメソッドはinline関数になります。
inline関数はODR(One definition rule)の例外として、同じ定義であれば複数のcppで定義することが許可されています。この辺はここが詳しいです。

そして、このODR例外は下記流れで実現されていると理解しています。
複数のcppでSingleton定義をインクルードした場合、Singleton::getInstance()内部のstatic変数instは各cppをコンパイルしたobjファイルに含まれてしまいます。しかし、これらのstatic変数instは全て同じ定義ですから、リンカにより重複が取り除かれます。

投稿2015/10/14 02:36

Chironian

総合スコア23272

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

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

yuba

2015/10/14 03:02

> inline関数はODR(One definition rule)の例外として、同じ定義であれば複数のcppで定義することが許可されています。 これが知りたかったことでした。ODRという規則も含め、勉強になりました。
guest

0

ベストアンサー

Singleton::getInstance()は「クラス定義中にて定義されるメンバー関数」であり、暗黙にinline指定されます。inline関数は複数ソースコード上で重複定義されても、最終的なプログラム中には単一実体しか存在しない事が保証されます。

メンバー関数より引用:

メンバー関数は、クラス定義の内側でも外側でも定義することができる。クラス定義の内側で定義されたメンバー関数を、inlineメンバー関数という。

inline指定子より引用:

インライン関数は、その関数を使用するすべての翻訳単位で、「定義」されていなければならない。インライン関数の定義は、すべての翻訳単位で、まったく同一でなければならない。

投稿2015/10/07 04:32

yohhoy

総合スコア6187

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

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

yuba

2015/10/07 04:35

Singletonクラスもそのメンバ関数も、(展開結果として)複数のcppに別々に宣言されているが同一実体だと認識されているということですね。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.53%

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

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

質問する

関連した質問