我有一个非常庞大的结构体,其中整个内容都是标量变量、枚举和标量数组(基于堆栈),除了一个std::string变量。
现在,这里是我的问题...
如果整个结构体的大小为0(就像它只包含标量一样),那么我可以将结构体设置为0吗?或者由于std::string的存在,这种做法不可行?我不确定memset对其内部表示会产生什么影响。
如果您要说它是好还是不好,请解释一下原因-我想知道它为什么是这样的 :)
我有一个非常庞大的结构体,其中整个内容都是标量变量、枚举和标量数组(基于堆栈),除了一个std::string变量。
现在,这里是我的问题...
如果整个结构体的大小为0(就像它只包含标量一样),那么我可以将结构体设置为0吗?或者由于std::string的存在,这种做法不可行?我不确定memset对其内部表示会产生什么影响。
如果您要说它是好还是不好,请解释一下原因-我想知道它为什么是这样的 :)
不行,这会覆盖字符串的内部状态并导致出现问题。您可以将所有POD内容包装在一个单独的结构中,并将其放入当前结构中,这样您就可以对该结构进行memset操作,并让字符串默认构造。
编辑:仅澄清一下,该字符串几乎肯定会存储指向其分配存储器的指针。 在您执行memset之前,该字符串的构造函数将始终运行(即使您在类型的构造函数中对this
执行了memset,字符串的构造函数也将首先运行)。 因此,您将覆盖此指针值,而它将不再指向其存储空间,而是指向NULL或某些几乎肯定无效的值。
以下是一个奇特的想法:假设您的类 Foo
有许多原始成员,在 Foo
的构造函数中保持未初始化状态,除了一个字符串:
class Foo
{
int a;
double b;
std::string s;
};
Foo::Foo()
会正确初始化字符串,但它不会关心其他任何事情。所以,在我们构造之前,让我们将内存清零!void * addr = ::operator new(sizeof(Foo));
std::memset(addr, 0, sizeof(Foo));
Foo * p = new (addr) Foo;
// later
p->~Foo();
::operator delete(addr);
将 std::string 成员归零是非常糟糕的想法,它会导致内存泄漏!千万不要这样做!
std::string
设置为0是一个坏主意,但实际上它可能会起作用,假设您的std:string
实现在构造时不分配内存。我想大多数std::string
都有3个指针(begin、end、capacity)和一个变量表示大小。如果没有进行任何分配,将所有这些指针设置为0应该是安全的。不用说这是不可移植的。 - Praetorianstd::string
从带有虚函数的基类派生,则memsetting会覆盖v-table并捣乱。我不确定标准中是否有任何内容防止std::string
基类具有虚函数。 - Praetorian