由于非平凡的可复制类型,gcc8引发编译错误

问题描述

class mapInfo
{
public:
    mapInfo();
    ~mapInfo();  
public:
    int dataType_m;

private:
    int *frequency;
};

//构造函数在这里定义。

    mapInfo::mapInfo() :
    dataType_m(0),frequency(NULL)
{
}  

//析构函数在这里定义

mapInfo::~mapInfo()
{
    free(frequency);
    frequency = NULL;
}

Result_t Maps::add(mapInfo &mapInfo_r)
{
    if (maps_mp == NULL)
    {
        numMaps_m = 1;
        maps_mp = (mapInfo *) calloc(1,sizeof(mapInfo));
    }
    else
    {
        numMaps_m++;
        maps_mp = (mapInfo *) realloc(maps_mp,numMaps_m*sizeof(mapInfo));
    }
    maps_mp[numMaps_m-1] = mapInfo_r; // Default copy constructor
    return 1;
}

使用gcc8进行编译时,出现以下编译错误。看起来像上面定义了析构函数,给出了gcc8的编译错误

如何解决此问题?

 error: 'void* realloc(void*,size_t)' moving an object of non-trivially copyable type 'class xyyz::mapInfo'; use 'new' and 'delete' instead [-Werror=class-memaccess]. 

解决方法

那根本不是正确的C ++。重写代码如下(我猜这里是关于frequency类型的,但是绝对不要在上面使用free

#include <vector>

class map_info
{
public:
    map_info();

private:
    int data_type;
    std::vector<int> frequency;
};
std::vector<map_info> maps_mp;

map_info::map_info() : data_type(0),frequency() {}

// …

void maps::add(map_info& map_info)
{
    maps_mp.push_back(map_info);
}

,
    maps_mp = (mapInfo *) realloc(maps_mp,numMaps_m*sizeof(mapInfo));

这不明智。如果一个对象不平凡,则不能将其从一个内存区域移动到另一个内存区域。

例如,考虑一个保留指向字符串的指针的字符串对象。看起来可能像这样:

class MyString
{
    char* inner_ptr;
    char buf[64];

    ...
};

它可能具有这样的构造函数:

MyString::MyString (const char* j)
{
     if (strlen(j) < 64)
         inner_ptr = buf;
     else
         inner_ptr = malloc (strlen(j) + 1);
     strcpy(inner_ptr,j);
}

还有这样的析构函数:

MyString::~MyString()
{
     if (buf != inner_ptr)
         free (inner_ptr);
}

现在,考虑一下如果对这些数组调用relloc会发生什么。短字符串的inner_ptr仍指向刚刚释放的旧对象的缓冲区。

错误消息很好地说明了此问题。使用realloc移动非平凡对象根本不合法。您必须构造一个新对象,因为该对象需要有机会处理其地址中的更改。