【发布时间】:2011-07-29 18:14:32
【问题描述】:
我有一个庞大的结构,其中所有内容都是标量变量、枚举和标量数组(基于堆栈),除了一个 std::string 变量。
现在,这是我的问题...
我可以将结构的整个大小都设置为 0(就像我希望它只是所有标量一样),或者如果 std::string 在那里是不可能的?我不确定 memset 会对它的内部表示做什么。
如果你要说它的好/坏,请解释原因 - 我想知道为什么会这样:)
【问题讨论】:
标签: c++
我有一个庞大的结构,其中所有内容都是标量变量、枚举和标量数组(基于堆栈),除了一个 std::string 变量。
现在,这是我的问题...
我可以将结构的整个大小都设置为 0(就像我希望它只是所有标量一样),或者如果 std::string 在那里是不可能的?我不确定 memset 会对它的内部表示做什么。
如果你要说它的好/坏,请解释原因 - 我想知道为什么会这样:)
【问题讨论】:
标签: c++
不,你不能,它会覆盖字符串的内部状态并导致坏事发生。您可以将所有 POD 内容包装在一个单独的结构中并将其放入当前结构中,这样您就可以对其进行 memset 并让字符串默认构造。
编辑: 澄清一下,字符串几乎肯定会存储一个指向它分配用于存储的内存的指针。字符串的构造函数总是在你可以 memset 之前运行(即使你在你的类型的构造函数中 memset this,字符串构造函数也会首先运行)。所以你会覆盖这个指针值,而不是指向它的存储,它会是一个指向 NULL 的指针,或者其他一些几乎绝对无效的值。
【讨论】:
memsetting 一个 std::string 到 0 是一个坏主意,但它可能真的有效,假设你的 std:string 实现不分配内存在构造。我想大多数std::strings 有 3 个指针(开始、结束、容量)和一个大小变量。如果没有进行分配,将所有这些设置为 0 应该是安全的。不用说这将是不可移植的。
std::string 派生自具有虚函数的基类,那么 memsetting 会覆盖 v-table 并搞砸一切。我不确定标准中是否有任何内容阻止 std::string` 基类具有虚函数。
这是一个奇特的想法:假设您的类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 成员归零是一个非常糟糕的主意,它会导致内存泄漏!千万不要这样做!
【讨论】: