在运行以下程序时,我遇到了段错误。但是,如果我评论memset,则不会出现段错误。无法找出原因。如果我需要清除结构内容(例如值),我们可以代替内存集做什么?
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
struct test
{
int value;
map<int, int> m;
};
void print(test *ptr)
{
cout << "map size() : " << ptr->m.size();
for(auto itr = ptr->m.begin(); itr != ptr->m.end(); ++itr)
{
}
}
int main()
{
test obj;
memset(&obj, 0, sizeof(obj));
print(&obj);
}
答案 0 :(得分:7)
std::map
不是POD结构,因此它具有内部结构(例如指针等),它将在其构造函数中初始化。
调用memset
时,您将整个结构置零,使对其的任何访问都不确定。
然后调用函数size()
,该函数使您的代码崩溃,因为它尝试读取现在位于零地址的任何内部。
要清除它,请使用memset
-> std::map
的指定方法代替clear()
。
答案 1 :(得分:6)
在不可复制的类型上调用memset
是未定义的行为(https://en.cppreference.com/w/cpp/string/byte/memset)。 std::map
不可复制,因此您的结构test
也不可复制。
如果要将value
设置为0,则可以仅调用obj.value = 0
,而如果要清除m
,则可以调用obj.m.clear()
。
答案 2 :(得分:2)
std::memset
仅适用于平凡可复制的对象。对于std::map
(是test
的组成部分)之类的东西,这是未定义的行为。
尽管default-initialized int
将是一个整数值,但是std::map
具有默认构造函数,并且将以其自己的正确簿记开始。但这被std::memset
取消了。
在C ++中,您几乎不需要std::memset
。
一个快捷而肮脏的选择是value-initialize test
。这将对非类类型的值(例如int
)进行零初始化:
test obj{}
要重置它,
obj = test{}
一个更好的选择是给test
一个默认的构造函数,该构造函数将m
设置为零。