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

How to write a copy constructor for a class with std::vector<unsigned char*> member variable

本文关键字:变量 构造函数 成员 复制 char vector std 何使用 lt unsigned gt      更新时间:2023-10-16

成员向量的简单赋值是否足够?

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

我的析构函数出现了一个漏洞,这让我怀疑复制构造函数可能是罪魁祸首。也可能是我的问题在别处

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

由于不存储分配的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++;
    }
}

你真的比使用我最初的建议要好得多。更不容易出错

你的vector包含指向堆内存的指针。假设你做widgetNamesA=widgetNamesB,其中一个超出了作用域。析构函数被调用,内存被删除。由于另一个对象指向相同的地址,它现在指向垃圾,任何访问都将导致崩溃。

您最好像其他答案建议的那样使用std::string()。

EDIT:如果不能使用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

那么标准库vector确实可以通过简单赋值复制。不幸的是,unsigned char*不是,矢量不知道这一点。因为你是手动处理指针的构造和销毁,这意味着你也必须手动处理复制。

更好的做法是使用std::string(或者std::basic_string)的vector,这样构造/复制/移动/销毁都是自动处理的。

相关文章: