ファクトリ クラスを実装しているstd::auto_ptr
ときに、理解できない動作に遭遇しました。問題を次の小さなプログラムに減らしたので、... 始めましょう。
次のシングルトン クラスを検討してください。
singleton.h
#ifndef SINGLETON_H_
#define SINGLETON_H_
#include<iostream>
#include<memory>
class singleton {
public:
static singleton* get() {
std::cout << "singleton::get()" << std::endl;
if ( !ptr_.get() ) {
std::cout << &ptr_ << std::endl;
ptr_.reset( new singleton );
std::cout << "CREATED" << std::endl;
}
return ptr_.get();
}
~singleton(){
std::cout << "DELETED" << std::endl;
}
private:
singleton() {}
singleton(const singleton&){}
static std::auto_ptr< singleton > ptr_;
//static std::unique_ptr< singleton > ptr_;
};
#endif
シングルトン.cpp
#include<singleton.h>o
std::auto_ptr< singleton > singleton::ptr_(0);
//std::unique_ptr< singleton > singleton::ptr_;
ここでリソースを管理するためのスマート ポインターの使用は、主にプログラム終了時のリークを回避する必要性によって決定されます。このコードを次のプログラムで使用します。
ああ
#ifndef A_H_
#define A_H_
int foo();
#endif
a.cpp
#include<singleton.h>
namespace {
singleton * dummy( singleton::get() );
}
int foo() {
singleton * pt = singleton::get();
return 0;
}
main.cpp
#include<a.h>
int main() {
int a = foo();
return 0;
}
今面白い部分。3 つのソースを個別にコンパイルします。
$ g++ -I./ singleton.cpp -c
$ g++ -I./ a.cpp -c
$ g++ -I./ main.cpp -c
この順序で明示的にリンクすると、次のようになります。
$ g++ main.o singleton.o a.o
すべてが期待どおりに機能し、次を標準出力に取得します。
singleton::get()
0x804a0d4
CREATED
singleton::get()
DELETED
代わりに、次の順序でソースをリンクする場合:
$ g++ a.o main.o singleton.o
私はこの出力を得ます:
singleton::get()
0x804a0dc
CREATED
singleton::get()
0x804a0dc
CREATED
DELETED
さまざまなコンパイラ ブランド (Intel および GNU) とバージョンを試しましたが、この動作はそれらの間で一貫しています。とにかく、リンクの順序に依存して動作するコードを見ることができません。
さらに、動作auto_ptr
に置き換えられunique_ptr
た場合は、常に私が正しいと期待するものと一致しています。
それは私に質問をもたらします:誰かがここで何が起こっているかについての手がかりを持っていますか?