5

ファクトリ クラスを実装している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た場合は、常に私が正しいと期待するものと一致しています。

それは私に質問をもたらします:誰かがここで何が起こっているかについての手がかりを持っていますか?

4

2 に答える 2