2012-07-10 6 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); 
} 

나는 이러한 오류 메시지가 얻을 컴파일하려고 :

vector<int> temp(size,0); 
vec = temp; 
: I가 잘못된 라인을 변경할 때, 그러나

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 

이제 장애없이 컴파일되고 원하는 동작을 얻고 내 벡터에 액세스 할 수 있습니다.

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

이 해결 방법은 정상이지만 작동하는 이유와 첫 번째 방법이 실패하는 이유를 알고 싶습니다. 미리 감사드립니다.

+2

가'새로운 vector' 당신이 당신의 멤버 변수에 할당 할 수 있도록하기위한이 아닌 값을 포인터를 반환' – Chethan

+2

당신이 자바에서 내 생각을 온 또는 C# 그리고 만약 그렇다면, 내 심각한 조언이다 vec' 좋은 C++ 서적을 먼저 입수하십시오. –

+0

그리고 항상 copy + paste 메소드를 통해 실제 코드를 게시하십시오. 당신이 게시 한 코드는 불완전합니다 –

답변

18

그냥 수행

MyClass::MyClass(int m_size) : size(m_size), vec(m_size, 0) 
이미 초기화 목록에 대해 아는 것 같은데

, 왜 직접이 벡터를 초기화하지? new 포인터를 반환하고 귀하의 경우 vec의 개체이기 때문에

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

불법입니다.

귀하의 두 번째 옵션 : 어떤 이득이 컴파일하지만

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

, 않습니다 추가 작업. 과제에 도달 할 때까지 이미 두 개의 벡터가 만들어져 버렸을 것입니다. 이 벡터 객체가 초기화되지 않은 것처럼 당신은 새로운 벡터 오브젝트에 대한 포인터를 할당하는

#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)); 그리고 그것도 작동하지만, 나는 initializer 목록을 사용합니다 감사합니다! – 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의 생성자에 도달하면 초기화됩니다 (기본 생성자가 호출 됨).

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 항목에 예약되어 있는지 확인하려면 일단 벡터가 생성되면 크기는 실제로 필요하지 않습니다. 따라서 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 
관련 문제