28

オブジェクトの構築中に発生する副作用のみを目的とするクラスがあるとします (たとえば、クラスをファクトリに登録するなど)。

class SideEffectCauser {
public:
  SideEffectCauser() { /* code causing side-effects */ }
};

また、いくつかの翻訳単位ごとに 1 回、オブジェクトにそのような副作用を作成させたいとします。SideEffectCauserそのような翻訳単位ごとに、.cpp ファイルの名前空間スコープでオブジェクトを配置できるようにしたいと考えています。

SideEffectCauser dummyGlobal;

しかし、C++03 標準の 3.6.2/3 は、.cpp ファイル内のオブジェクトまたは関数が使用されない限り、このオブジェクトを構築する必要がまったくないことを示唆しています。オブジェクトが初期化されないことがあります。

一方、クラス名を保持する文字列からオブジェクトをインスタンス化する方法はありますか? SideEffectCauser機能すると主張されているソリューションがあり、グローバルとしてではなく、静的データメンバーとしてのようなタイプのオブジェクトを使用することに基づいていることに注意してください。

class Holder {
  static SideEffectHolder dummyInClass;
};

SideEffectHolder Holder::dummyInClass;

dummyGlobalとはどちらdummyInClassも非ローカルな静的ですが、C++03 標準の 3.6.2/3 をよく見ると、その節が名前空間スコープのオブジェクトにのみ適用されることがわかります。クラススコープの非ローカル静的が動的に初期化される時期を示すC++03標準には実際には何も見つかりませんが、9.4.2/7は、名前空間の非ローカル静的と同じ規則がそれらに適用されることを示唆しています範囲。

dummyInClass質問 1: C++03 では、 がよりも初期化される可能性が高いと考える理由はありますdummyGlobalか? または、同じ翻訳単位内の関数またはオブジェクトが使用されていない場合、両方が初期化されない可能性がありますか?

質問 2: C++11 で何か変更はありますか? 3.6.2 と 9.4.2 の文言は C++03 バージョンと同じではありませんが、私が知る限り、上記のシナリオで指定された動作上の違いはありません。

質問 3:SideEffectHolder関数本体の外側のようなクラスのオブジェクトを使用して、副作用を強制的に発生させる信頼できる方法はありますか?

4

2 に答える 2

1

唯一の信頼できる解決策は、特定のコンパイラとランタイム用にこれを設計することだと思います。共有ライブラリでのグローバルの初期化をカバーする標準はありません。これは、ローダーに大きく依存し、OS に依存するため、最も複雑なケースだと思います。

Q1: いいえ Q2: 実用的な意味ではありません Q3: 標準的な方法ではありません

于 2012-12-31T11:16:51.190 に答える
0

Linuxでg ++ / C ++ 11と同様のものを使用しており、工場を期待どおりに登録しています。関数が呼び出されない理由がわかりません。あなたが説明したことが実装される場合、そのユニット内のすべての関数が初期化関数を呼び出さなければならないことを意味します。どうすればそれができるのかよくわかりません。名前空間という名前が付いていますが、私の工場も名前空間内にあります。しかし、なぜ呼び出されないのかわかりません。

namespace snap {
namespace plugin_name {
class plugin_name_factory {
public:
  plugin_name_factory() { plugin_register(this, name); }
...
} g_plugin_name_factory;
}
}

とにかく、C++ では static キーワードを使用しないでください。グローバルよりも静的な定義を持つ方が遅いことがよくあります。

于 2012-12-13T10:02:17.997 に答える