如何使用std :: vector <unsigned char * =“”>成员变量</unsigned>为类编写复制构造函数

时间:2011-08-29 18:22:08

标签: c++

成员向量的简单分配是否足够?

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;
};

我在析构函数中遇到了一个问题,这让我怀疑复制构造函数可能是罪魁祸首。或者可能是我的问题在其他地方

编辑
添加缓冲区的长度。这不是完整的类def我只是想提供足够的信息来征求帮助 不,我不能使用std :: string,因为我想与可以写入缓冲区的c函数共享成员向量

3 个答案:

答案 0 :(得分: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++;
    }
}

尽管如此,你真的可以更好地使用我的一个原始建议。更不容易出错。

答案 1 :(得分:2)

您的向量包含指向堆内存的指针。假设您执行widgetNamesA=widgetNamesB,其中一个超出范围。调用析构函数,并删除内存。由于另一个对象指向相同的地址,它现在指向垃圾,任何访问都会导致崩溃。

与其他答案建议一样,你最好使用std :: string()。

编辑:如果你不能使用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

答案 2 :(得分:0)

然后,通过简单的赋值,标准库矢量确实可以复制。不幸的是,unsigned char*不是,而矢量不知道。由于您手动处理指针构造和销毁,这意味着您也必须手动处理副本。

更好的做法是使用std :: string(或者std :: basic_string)的向量,以便自动处理构造/复制/移动/销毁。