37

std::vector<int>インスタンス変数としてを持っているクラスを設計しています。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

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

4

3 に答える 3

48

ただ行う:

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

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

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

newポインタを返し、あなたの場合vecはオブジェクトであるため、は不正です。

2番目のオプション:

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

コンパイルされますが、利益を得るために余分な作業を行います。割り当てに到達するまでに、2つのベクトルがすでに作成され、後で破棄されているはずです。

于 2012-07-10T14:26:14.377 に答える
15

ベクトルの使用はクラスで合法です。問題はそれをどのように初期化するかです。

#include <vector>

class MyClass {
public:
    MyClass(int m_size);

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

このベクトルオブジェクトが初期化されていないかのように、新しいベクトルオブジェクトにポインタを割り当てています。

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

これを本当に機能させたい場合は、vecオブジェクトを次のように宣言する必要があります。

vector<int> * vec;

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

MyClass::~MyClass {
    delete vec;
}

newパーティクルをドロップしたときになぜ機能したのですか?新しいオブジェクトを作成し、クラス内のオブジェクトvector上書きしているためです(ただし、これは元のオブジェクトが正しく削除されることを保証するものではありません)。

実際にそれを行う必要はありません。MyClassvectorのコンストラクターに到達すると、オブジェクトはすでに初期化されています(デフォルトのコンストラクターが呼び出されます)。sizeメモリがアイテム用に予約されていることを確認したいだけの場合:

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

ベクトルにsize要素を含める場合は、次のようにします。

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

最後に、コメント投稿者の1人が指摘しているように、ベクトルが作成された後は、サイズは実際には必要ありません。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;
}

お役に立てれば。

于 2012-07-10T14:36:39.433 に答える
2
#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

これは、他の引数が存在する、または存在しない、または存在しないベクトルを使用して、または使用せずにクラスを初期化するオプションを提供するクラスを作成する方法を示します。

于 2018-02-17T21:28:37.890 に答える