2011-08-29 3 views
1

멤버 벡터를 간단히 할당하는 방법은 무엇입니까?std :: vector <unsigned char *> 멤버 변수를 사용하여 클래스의 복사본 생성자를 작성하는 방법

class WidgetNames 
{ 
    WidgetNames(int sz) 
    { 
     unsigned char* c = new unsigned char[ sz ]; 
     memset(c,0,sz); 
     m_names.push_back(c); 
      m_len.push_back(sz); 
    } 
    ~WidgetNames() 
    { 
     for (size_t i = 0 ; i < m_names.size() ; ++i) 
     { 
      if(m_names[i] != NULL) 
      { 
       delete [] m_names[i]; 
      } 
     } 
    } 
    WidgetNames(const WidgetNames &other) 
    { 
     m_names = other.m_names; 
    } 
    std::vector<unsigned char*> m_names; 
    std::vector<int> m_len; 
}; 

복사 생성자가 범인인지 의심스럽게 만드는 내 소멸자에 크레이치가 나타납니다. 아니면 다른 곳에서 내 문제가 될 수도 있습니다.

EDIT
버퍼 길이가 추가되었습니다. 이것은 완전한 클래스 정의가 아닙니다. 단지 도움을 청하기에 충분한 정보를 제공하고 싶었습니다.
아니요, std :: string을 사용할 수 없습니다. 멤버 벡터를 버퍼에 쓸 수있는 c 함수와 공유하기 때문에

+1

'std :: string'의 벡터를 사용할 수없는 이유는 무엇입니까? –

+0

@Kerrek SB 내가 std :: string을 사용할 수없는 이유는 데이터베이스 저장 프로 시저에 IN/OUT 매개 변수로 전달하기 때문입니다. 즉, 데이터베이스 드라이버가 결과를 문자열로 반환합니다.거기에 std :: string을 만드는 방법이있을 수 있습니다. 만약 내가 있다면 매우 행복 할 것입니다. – gonzales

+2

물론 : 문자열이나 벡터를 가져 와서 크기를'resize()'하고'& x [0]'이나'.data()'를 API. –

답변

5

당신은

사용해보십시오 복사 생성자를 할 수있는 방법이없는 당신이 할당 char 배열의 크기를 저장하지 않기 때문에 :

std::vector< std::vector< unsigned char > > m_names; 

귀하의 생성자는 다음과 같을 것이다는 .

WidgetNames(int sz) 
{ 
    std::vector< unsigned char > c; 
    c.resize(sz); 
    m_names.push_back(c); 
} 

대신에. 이 문자열처럼 보이는대로 또는, 더 쉽게, 당신은 단지 사용하는 저장하고 편집

std::vector<std::string> m_names; 

: 위의 당신이 당신의 복사 생성자에서 다음을 수행 할 필요가 견딜 수 없습니다.

WidgetNames(const WidgetNames &other) 
{ 
    int i = 0; 
    while(i < m_names.size()) 
    { 
     delete[] m_names[i]; 
     i++; 
    } 

    m_names.resize(other.m_names.size()); 
    m_len.resize(other.m_len.size()); 
    i = 0; 
    while(i < m_names.size()) 
    { 
     m_len[i] = other.m_len[i]; 
     m_names[i] = new unsigned char[m_len[i]]); 
     memcpy(m_names[i], other.m_names[i], m_len[i]); 
     i++; 
    } 
} 

정말로 내 원래 제안 중 하나를 사용하면 훨씬 나아질 수 있습니다. 오류가 거의 없습니다.

+0

내 편집을 참조하십시오. 나는 크기를 저장한다 – gonzales

+0

@Gonzales : Edited. 그러나 여전히 원래의 조언을 들어라. – Goz

+0

할당 전에 할당 된 메모리는 어떻게됩니까? 아래의 dario_ramos의 대답을 보면 그가 과제를 수행하기 전에 기억을 풀고 있습니다. 나는 이것이 필요하지 않았지만 생각을 다시하게했다. 나는 당신이 단순히 낡은 벡터의 크기를 조정하고있는 것을 본다. – gonzales

0

표준 라이브러리 벡터는 간단한 할당을 통해 실제로 복사 가능합니다. 불행히도 unsigned char*은 아니며 벡터는이를 알지 못합니다. 포인터 생성과 파기를 수동으로 처리하고 있기 때문에 수동으로 복사본을 처리해야 함을 의미합니다.

더 나은 연습은 std :: string (또는 std :: basic_string)의 벡터를 사용하여 구성/복사/이동/삭제가 모두 자동으로 처리되도록하는 것이 좋습니다.

2

벡터에 힙 메모리에 대한 포인터가 들어 있습니다. widgetNamesA=widgetNamesB을하고 그 중 하나가 범위를 벗어난다고 가정 해보십시오. 소멸자가 호출되고 메모리가 삭제됩니다. 다른 객체가 동일한 주소를 가리키고 있기 때문에 이제는 쓰레기를 가리키고 모든 액세스는 충돌을 일으킬 것입니다.

다른 답변과 마찬가지로 std :: string()을 사용하는 것이 좋습니다.

편집 : 당신이 표준 : : 문자열을 사용할 수없는 경우, 다음과 같은 일을 할 : 당신이 스마트 포인터를 사용하는 경우

WidgetNames(const WidgetNames &other){ 
    //Release owned memory 
    for(int i=0; i<m_names.size(); i++){ 
     delete m_names[i]; 
    } 
    m_names.clear(); 
    //Allocate new memory and copy right side's contents 
    for(int i=0; i<other.m_names.size(); i++){ 
     m_names.push_back(new unsigned char[other.m_len[i]]); 
     memcpy(m_names[i], other.m_names[i], other.m_len[i]); 
    } 
} 

(같은 std::tr1::shared_ptr가), 당신은에 대한 delete을 잊을 수있다.

관련 문제