2012-07-10 8 views
12

std::vector<int>をインスタンス変数として持つクラスを設計しています。実行時にサイズを設定する必要があるので、std::vectorを使用しています。クラスコンストラクタでstd :: vectorを設定します

my_class.h: 

#include <vector> 
using std::vector; 
class MyClass { 
    int size; 
    vector<int> vec; 
} 

my_class.cc: 

#include "my_class.h" 
using std::vector 
MyClass::MyClass(int m_size) : size(m_size) { 
    vec = new vector<int>(size,0); 
} 

私がコンパイルしようとすると、私はこれらのエラーメッセージを得る:

g++ -c -Wall my_class.cc -o my_class.o 

my_class.cc: In constructor ‘MyClass::MyClass(int): 

    my_class.cc:4 error: no match for ‘operator=’ in ‘((MyClass*)this)->My_Class::vec = ((*(const allocator_type*)(& std::allocator<int>())), (operator new(24u), (<statement>, ((std::vector<int>*)<anonymous>))))’ 

make: *** [my_class.o] Error 1 

しかし、私は、問題の行を変更する場合:

vector<int> temp(size,0); 
vec = temp; 
ここに私のコードの関連部分は、

これは問題なくコンパイルされ、目的の動作が得られ、ベクターにアクセスできます

vec[i] // i having been defined as an int yada yada yada 

この回避策は問題ありませんが、なぜ動作し、最初の方法が失敗するのかを理解したいと思います。前もって感謝します。

+2

あなたのメンバ変数に割り当てることができるようにするために私の推測では、あなたはJavaやC#から来ているそうであれば、私の重大なアドバイスがある – Chethan

+2

vec' '新しいvector'は'、ポインタでない値を返します。 C++の最初の優れた本を最初に手に入れるために。 –

+0

そして、実際のコードは必ずcopy + pasteメソッドで投稿してください。あなたが投稿したコードは不完全です –

答えて

18

ちょうど行います

MyClass::MyClass(int m_size) : size(m_size), vec(m_size, 0) 

あなたはすでに、なぜそこに直接ベクトルを初期化しないで、初期化子リストについて知っているように見えますか?

vec = new vector<int>(size,0); 

newポインタを返し、あなたのケースでvecがオブジェクトであるため、違法です。

あなたの番目のオプション:

vector<int> temp(size,0); 
vec = temp; 

それはコンパイルが、無利益のために余分な作業を行います。あなたが割り当てに達すると、すでに2つのベクトルが構築され、その後破棄されます。このベクトルオブジェクトが初期化されていなかったかのようにあなたは、新しいベクトルオブジェクトへのポインタを代入している

#include <vector> 

class MyClass { 
public: 
    MyClass(int m_size); 

    // ... more things... 
private: 
    int size; 
    vector<int> vec; 
} 

+1

IIRCこれは、初期化の順序のためにGCCで警告を発します。クラス内のメンバ変数と同じ方法でイニシャライザリストの初期化を行う必要があります。 – Fiktik

+0

コメントのおかげで、私はvec = *(新しいベクトル(szie、0))をやってみました。それも働いたが、私はイニシャライザのリストを使用していただきありがとうございます! – fenkerbb

+0

@ user1269950あなたがしたことは間違っています - それはメモリリークを作成します。 'new'はヒープ上にメモリを割り当て、そこにオブジェクトを作成し、そこへのポインタを返します。あなたがしたことは、そのオブジェクトの内容をメンバーオブジェクトに割り当てて、元のオブジェクトを忘れてしまったことです。 'new'を呼び出すときには常に(ポ​​インタで)返されるアドレスを保存し、最終的にそのポインタに対して' delete'を呼び出さなければなりません! – Fiktik

8

ベクターの使用は、あなたのクラスでは合法ですが、問題は、あなたがそれを初期化する方法です。

vec = new vector<int>(size,0); 

あなたは本当にこれが仕事をしたい場合は、としてあなたvecオブジェクトを宣言する必要があります

vector<int> * vec; 

とデストラクタを追加することを忘れないでください:

MyClass::~MyClass { 
    delete vec; 
} 

なかった理由newパーティクルを落としたときに機能しますか?新しいオブジェクトvectorを作成しているので、クラス内のオブジェクトはに上書きされます(ただし、元のオブジェクトを正しく削除することはできません)。

実際に行う必要はありません。 vectorオブジェクトは、MyClassのコンストラクタに到達した時点で既に初期化されています(デフォルトコンストラクタが呼び出されます)。コメンターの1が指摘するように、

最後
MyClass::MyClass(int m_size): size(m_size), vec(m_size, 0) 
    {} 

:あなたはあなたのベクトルは、その後size要素を持つようにしたい場合は

MyClass::MyClass(int m_size): size(m_size) { 
    vec.reserve(size); 
} 

:あなただけのメモリがsizeアイテムのために予約されていることを確認したい場合ベクトルが構築されると、サイズは実際には必要ありません。だから、sizeメンバーを取り除くことができます:

class MyClass { 
public: 
    MyClass(int m_size): vec(m_size, 0) 
     {} 

    unsigned int getSize() const 
     { return vec.size(); } 

    // ... more things... 
private: 
    vector<int> vec; 
} 

これは役に立ちます。

+1

@OP - 'vector'はそのサイズを知っているので、' size'がすべて 'vector'の要素数を追跡しているなら、' size'を取り除くことを提案します。 –

+0

本当に、私はあなたのコメントを含むように私の答えを変更します。 – Baltasarq

1
#include <vector> 
#include <iostream> 
#include <string> 
#include <typeinfo> 

using std::cout; 
using std::endl; 
using std::string; 
using std::vector; 
using std::to_string; 

class Parse 
{ 
private: 
    string   m_str; 
    vector<string> m_vec; 
public: 
    // Constructor with all defaults (1 of 4 constructors) 
    Parse(){ 
     cout << "\ncreating class with all default values\n"; 
     m_str = ""; 
     m_vec.push_back("");  
    } 

    // Constructor with all cases used 
    Parse (string   &tmp_str, 
      vector<string> tmp_vec): 

      m_str   (tmp_str), 
      m_vec   (tmp_vec) 
    { 
     cout << "Your vector contains " + to_string(m_str.size()) + " arguments\n"; 
    } 

    // Constructor with other contents given but not vector 
    Parse (string   &tmp_str): 
      m_str   (tmp_str) 
    { 
     m_vec.push_back(""); 
    } 
    // Constructor with only Vector given but not other contents 
    Parse (vector<string> tmp_vec): 
      m_vec   (tmp_vec) 
    { 
     m_str = ""; 
    } 

    string get_str_var(){return m_str;} 

    void classed_print_vector_strings() 
    { 
     for (string i : m_vec){ cout << i << " \n";} 
    } 

}; 



// rm ./class_vector; g++ class_vector.cpp -o class_vector -std=c++17; ./class_vector arg1 arg2 arg3 

int main(int argc, char *argv[]) 
{ 
    // turn **argv to a vector 
    vector<string> args(argv, argv + argc); 
    // iterate from argv through argv+argc 

    // initialize with default arguments. 
    Parse tracker1; 
    // initalize with all used arguments 
    Parse tracker2(args[0], args); 
    // initalize with only the vector 
    Parse tracker3(args); 
    // initalzie without the vector, but with another arg 
    Parse tracker4(args[0]); 

    cout << "\nTracker 1 ---------------------\n"; 
    tracker1.classed_print_vector_strings(); 
    cout << "\nTracker 2 ---------------------\n"; 
    tracker2.classed_print_vector_strings(); 
    cout << "\nTracker 3 ---------------------\n"; 
    tracker3.classed_print_vector_strings(); 
    cout << "\nTracker 4 ---------------------\n"; 
    tracker4.classed_print_vector_strings(); 


    return 0; 
} 

// rm ./class_vector; g++ class_vector.cpp -o class_vector -std=c++17; ./class_vector arg1 arg2 arg3 

// This will show you how to create a class that will give 
// you the option to initilize the class with or without 
// the vector with other arguments present and/or not present. 

// My Background. . . 
// github.com/Radicalware 
// Radicalware.net 
// https://www.youtube.com/channel/UCivwmYxoOdDT3GmDnD0CfQA/playlists 
関連する問題