2012-07-10 96 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 
相关问题