2009-05-11 20 views
2

整数引数を取るクラスオブジェクトの配列を作成しようとしています。私はこの単純なコードで何が間違っているのか分かりません。助けてもらえますか?オブジェクトの配列を作成する手助けが必要

#include <fstream> 
#include <iostream> 
using namespace std; 

typedef class Object 
{ 
int var; 
public: 
Object(const int& varin) : var(varin) {} 
} Object; 

int main (int argc, char * const argv[]) 
{ 
for(int i = 0; i < 10; i++) 
{ 
    Object o(i)[100]; 
} 

return 0; 
} 

答えて

8

C++では、あなたはclass ESとstruct秒間typedef秒を必要としません。だから、:

class Object 
{ 
int var; 
public: 
Object(const int& varin) : var(varin) {} 
}; 

はまた、記述的な名前はObjectがはるかに虐待され、常にpreferrableです。

int main (int argc, char * const argv[]) 
{ 
int var = 1; 

Object obj_array[10]; // would work if Object has a trivial ctor 

return 0; 
} 

そうでない場合は、あなたのケースで:

int main (int argc, char * const argv[]) 
{ 
int var = 1; 

Object init(var); 
Object obj_array[10] = { var, ..., var }; // initialize manually 

return 0; 
} 

けれども、本当にあなたがvector

#include <vector> 
int main (int argc, char * const argv[]) 
{ 
int var = 1; 

vector<Object> obj_vector(10, var); // initialize 10 objects with var value 

return 0; 
} 
4

dirkgentlyの荒廃を探す必要がありますが、C++でのアイテムの配列のかなり正確な表現ですが、どこ彼は別の値でそれぞれを初期化しようとしているのと同じ値で配列のすべての項目を初期化しています。

質問に答えるには、intコンストラクタパラメータを使用するオブジェクトの配列を作成します。あなたはできません、オブジェクトが配列が割り当てられたときに作成され、あなたのコンパイラが不平を言うコンストラクタがなければ、コンパイラは不平を言うでしょう。しかし、あなたのオブジェクトへのポインタの配列を初期化することができますが、実際にはベクトルにもっと柔軟性があるので、次の例ではstd :: vectorを使用します。

各オブジェクトに個別の値を設定する場合は、オブジェクトのそれぞれを個別に初期化する必要があります。この2つの方法のいずれかを実行できます。スタック上、またはヒープ上に置くことができます。最初にオンザスタックを見てみましょう。

単一の引数をとり、explicitとしてマークされていないコンストラクタは、暗黙のコンストラクタとして使用できます。これは、その型のオブジェクトが期待される場所ではなく、単一のパラメータ型のインスタンスを使用できることを意味します。この例では、Objectクラスのベクトルを作成し、100個のObjectを追加します(push_backはアイテムをベクトルに追加します)。push_backに整数を渡します。これは暗黙的に整数を渡すオブジェクトを作成します。

#include <vector> 
int main() { 
    std::vector<Object> v; 

    for(int i = 0; i < 100; i++) { 
     v.push_back(i); 
    } 
} 

それとも約明示的にする:これらの例で

#include <vector> 
int main() { 
    std::vector<Object> v; 

    for(int i = 0; i < 100; i++) { 
     v.push_back(Object(i)); 
    } 
} 

、オブジェクトのすべてのオブジェクトが場合、オブジェクトのでコピーが発生し、forループの範囲にスタック上に割り当てられていますベクトルにプッシュされます。多数のオブジェクトをコピーすると、特にオブジェクトのコピーが高価な場合にパフォーマンスの問題が発生する可能性があります。私たちのオブジェクトはヒープ上に作成されたので、私たちがいることを確認する必要があり

#include <vector> 
int main() { 
    std::vector<Object*> v; 

    for(int i = 0; i < 100; i++) { 
     v.push_back(new Object(i)); 
    } 

    for(int i = 0; i < 100; i++) { 
     delete v[i]; 
    } 
} 

:このパフォーマンス上の問題を回避する

1つの方法は、ベクトル内のオブジェクトにヒープとストアのポインタ上のオブジェクトを割り当てることですデコンスターを呼び出すためにそれらを削除し、メモリを解放すると、このコードは2番目のループでそれを行います。

手動でdeleteを呼び出すことはそれ自身の警告です。これらのポインタを他のコードに渡すと、ポインタを所有している人とそれらを削除する必要がある人のトラックをすばやく見つけることができます。この問題を解決するための簡単な方法は、参照カウントポインタであるboost::shared_ptrまたはtr1::shared_ptrのいずれかを参照して、ポインタの寿命を追跡するために、スマートポインタを使用することです:

#include <vector> 
int main() { 
    std::vector<shared_ptr<Object> > v; 

    for(int i = 0; i < 100; i++) { 
     Object* o = new Object(i); 
     v.push_back(shared_ptr<Object>(o)); 
    } 
} 

あなたはshared_ptrのコンストラクタは、明示的であることがわかりますこれは意図的に、開発者が意図的にポインタを共有ポインタに詰め込んでいることを確認するために行われます。オブジェクトへのすべての参照が解放されると、オブジェクトはshared_ptrによって自動的に削除され、その寿命について心配する必要はありません。

+0

ありがとうフォローアップ。これは大きな助けにもなりました! – banDedo

0

配列に固執する場合は、手動で初期化するか、デフォルトコンストラクタを使用する必要があります。しかし、デフォルトの引数でコンストラクタを作成することで、何らかの制御を得ることができます。これはコンパイラによってデフォルトコンストラクタとして扱われます。たとえば、次のコードは数字0、...、9を順に出力します。 (ただし、配列内のオブジェクトを順番に構築する必要があるということは、標準では必ずしも明らかではありません。実装に依存している可能性があります)。

#include <iostream> 

using namespace std; 

struct A { 
    int _val; 

    A(int val = initializer()) : _val(val) {} 

    static int initializer() { static int v = 0; return v++; } 
}; 

int main() 
{ 
    A a[10]; 
    for(int i = 0; i < 10; i++) 
     cout << a[i]._val << endl; 
} 
関連する問題