2012-07-10 71 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

'新VECTOR'返回一個指針不是一個值,你可以把它分配給你的成員變量'vec' – Chethan 2012-07-10 14:33:05

+2

我的猜測是你來自Java或C#如果是這樣,我認真建議是首先要獲得一本好的,介紹性的C++書籍。 – 2012-07-10 15:11:16

+0

請始終通過複製粘貼方法發佈實際代碼。你發佈的代碼是不完整的 – 2012-07-10 15:11:51

回答

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; 

雖然它編譯,做額外的工作。到達作業時,兩個向量已經被構建並在之後丟棄。

+1

IIRC由於初始化的順序,這將導致GCC警告 - 您應該在初始化程序列表中以與該類中的成員變量相同的方式對初始化進行排序。 – Fiktik 2012-07-10 14:33:25

+0

感謝您的意見,基於它我試圖做vec = *(新矢量(szie,0));那也行,但我會用初始化列表謝謝! – fenkerbb 2012-07-10 14:34:21

+0

@ user1269950你所做的是錯誤的 - 它會產生內存泄漏。 'new'在堆上分配一個內存,在那裏創建一個對象並返回一個指向它的指針。你所做的是將該對象的內容分配給你的成員對象,然後忘掉原來的對象 - 但它仍然是永久分配的。當你調用'new'時,你總是必須保存它返回的地址(在一個指針中)並最終在那個指針上調用'delete'! – Fiktik 2012-07-10 14:43:35

8

使用載體在類的法律,問題是你如何初始化:

#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覆蓋您班上的一個(但不能保證原始的一個被正確刪除)。

你其實並不需要那樣做。當您到達MyClass的構造函數時,您的vector對象已經初始化(其默認構造函數調用)。如果你只是想確保內存保留給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) 
    {} 

最後,作爲評論者之一指出一旦構建了矢量,尺寸實際上並不需要。所以你可以擺脫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'。 – 2012-07-10 15:00:17

+0

非常真實,我會修改我的答案以引起您的評論。 – Baltasarq 2012-07-10 18:59:57

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 
相關問題