3

一般的なアドバイスをお願いします。以下のコードは完全にコンパイルされ、私が扱うコードの構造を大まかに表しています。簡単に言えば、ベース クラス (Class1) から派生した一連のオブジェクトと、その他のパラメーターをある場所から別の場所に渡したいと考えています。より正確には、親クラスのさまざまな子クラスを実装し、それらのインスタンスを収集して、パラメーターで処理するために渡します。

問題は、オブジェクトのベクトルまたはポインターのベクトルを使用することをお勧めしますか? これが何らかの理由でより良い/安全である/メモリリークが少ない/などC++11である場合、 ( std::unique_ptrstd::shared_ptr)からいくつかの新しいものに行くことを気にしません。誰かが間違いなくそのような場合のコンテナについてアドバイスしたり、. C++11

p/s/ here UncleBens は、ポインターを使用すると、例外がスローされた場合にメモリ リークが発生する可能性があると述べています。それで、私は本当にタスクにスマートポインターを使用する必要がありますか? これはどのように見えますか?

p/p/s/ 面白いことに、実際の例では、からこれらのオブジェクト を使用しようとするとBus error: 10が表示されます。ただし、単純なケースではエラーを再現できません...Class2std::vector< Container<d>*> / std::vector< Container<d>>

#include <string>
#include <iostream>
#include <vector>


template<int dim>
class Class1 {
   public:

     Class1() {};
    ~Class1() {}; 

};

template<int dim>
class Class2 : public Class1<dim>
{
   public:
     Class2() : 
       Class1<dim>() {}; 

 };

template <int dim>
class Container
{
  public:
     Container( Class1<dim> & f, int param1) : c1(f), param_(param1) {}

  Class1<dim>  & c1;
      int param_;
 };

 static const int d = 2; 

 int main() 
 {
    int p = 1;
    Class2<d> c2;
    std::vector< Container<d> *> p_list;
    std::vector< Container<d> > list;
    {
      p_list.push_back ( new Container<d> ( c2,p ) ); 
    }
    std::cout<<"from pointers: "<<p_list[0]->param_<<std::endl;

    {
      list.push_back( Container<d> ( c2,p ) );
    }
    std::cout<<"from objects: "<<list[0].param_<<std::endl;
 }
4

1 に答える 1

0

まず、Class1 のデストラクタは仮想としてマークする必要があります。そうしないと、派生クラス (たとえば Class2) のインスタンスが破棄されたときに、そのデストラクタが正しく呼び出されません。

あなたの質問に関しては、オブジェクトのコンテナを使用した結果は次のとおりです。

  • コンテナーはオブジェクトのコピーを作成する必要がある場合があるため、コピー コンストラクターがあることを確認する必要があります (この例のクラスは、コンパイラーによって生成された既定のクラスを取得します)。オブジェクトのコピーはパフォーマンスに影響を与える可能性があり、コピーのセマンティクスを適切に定義する必要があります (深いか浅いか、つまり、class1 オブジェクトの新しいコピーを作成するか、単に参照をコピーするか)。
  • ポリモーフィズムを持つことはできないため、Container をサブクラス化してから、ベースとサブクラスのインスタンスを同じコンテナーに配置することはできません。
  • コンテナーによっては、オブジェクトがメモリ内で連続することになり (ベクターの場合)、パフォーマンスが向上する可能性があります。

生のポインターのコンテナーを使用する場合、コンテナーはポインターを (より高速に) コピーするだけで済み、含まれている型の派生インスタンスを追加できます。欠点は、使用後にオブジェクトを手動で破棄する必要があることと、前述のように、メモリ リークが発生しやすいことです。

shared_ptrs には生のポインターと同様の利点/欠点がありますが、主な利点は、何も参照されなくなったときに shared_ptr がオブジェクトを破棄することです。これにより、メモリ リークが発生する可能性が低くなります (ただし、それでも例外が含まれる場合はそうしてください)。

これらのオブジェクトをさらに処理するために引き渡すことを考えると、shared_ptr ベースのアプローチが適切なオプションであると言えます。生のポインタに加えて共有 ptr を使用した場合の結果は次のとおりです。

  • スレッドセーフにするために、ほとんどの shared_ptr 実装はロックをチェック/設定する必要があるため、パフォーマンスのオーバーヘッドが発生する可能性があります (これには OS へのシステムコールが含まれる場合があります)。
  • オブジェクト間の循環参照を導入することで、メモリ リークが発生する可能性があります。
  • C++11 を実装するコンパイラを使用するか、外部ライブラリを使用する必要があります (ほとんどの人はブーストを使用します)。

shared_ptrs を使用した例は次のようになります (テストされていません)。

#include <string>
#include <iostream>
#include <vector>

template<int dim>
class Class1 {
   public:
       Class1() {};
       virtual ~Class1() {}; 

};

template<int dim>
class Class2 : public Class1<dim>
{
    public:
        Class2() : 
        Class1<dim>() {}; 

};

template <int dim>
class Container
{
    public:
       Container( boost::shared_ptr<Class1<dim>> f, int param1) : c1(f), param_(param1) {}

       boost::shared_ptr<Class1<dim>> c1;
       int param_;
};

static const int d = 2;

int main() 
{
    int p = 1;
    boost::shared_ptr<Class1<d>> c2 = boost::make_shared<Class2<d>>();

    std::vector<boost::shared_ptr<Container<d>>> list;
    list.push_back(boost::make_shared<Container<d>>(c2,p));

    std::cout << "from objects: " << list[0]->param_ << std::endl;
}

要約すると、コンテナーを受け取るコードがコンテナーへの参照をどこにも格納せず、ポリモーフィズムが必要ない場合、オブジェクトのコンテナーはおそらく問題ありません。コンテナを受け取るコードがコンテナをどこかに保存する必要がある場合、および/またはポリモーフィック コンテナが必要な場合は、共有 ptr を使用します。

于 2013-03-31T17:29:33.800 に答える