【问题标题】:memset structure with std::string contained包含 std::string 的 memset 结构
【发布时间】:2011-07-29 18:14:32
【问题描述】:

我有一个庞大的结构,其中所有内容都是标量变量、枚举和标量数组(基于堆栈),除了一个 std::string 变量。

现在,这是我的问题...

我可以将结构的整个大小都设置为 0(就像我希望它只是所有标量一样),或者如果 std::string 在那里是不可能的?我不确定 memset 会对它的内部表示做什么。

如果你要说它的好/坏,请解释原因 - 我想知道为什么会这样:)

【问题讨论】:

    标签: c++


    【解决方案1】:

    不,你不能,它会覆盖字符串的内部状态并导致坏事发生。您可以将所有 POD 内容包装在一个单独的结构中并将其放入当前结构中,这样您就可以对其进行 memset 并让字符串默认构造。

    编辑: 澄清一下,字符串几乎肯定会存储一个指向它分配用于存储的内存的指针。字符串的构造函数总是在你可以 memset 之前运行(即使你在你的类型的构造函数中 memset this,字符串构造函数也会首先运行)。所以你会覆盖这个指针值,而不是指向它的存储,它会是一个指向 NULL 的指针,或者其他一些几乎绝对无效的值。

    【讨论】:

    • 不争论 memsetting 一个 std::string 到 0 是一个坏主意,但它可能真的有效,假设你的 std:string 实现不分配内存在构造。我想大多数std::strings 有 3 个指针(开始、结束、容量)和一个大小变量。如果没有进行分配,将所有这些设置为 0 应该是安全的。不用说这将是不可移植的。
    • 最好的情况,通过覆盖指针,你会泄漏字符串分配的所有内存。
    • @Praetorian - 你是对的,但这是一个糟糕的想法,我宁愿把它归类为你不能做的事情。
    • @Node 我同意。我在发表评论时忘记的另一件事是,如果std::string 派生自具有虚函数的基类,那么 memsetting 会覆盖 v-table 并搞砸一切。我不确定标准中是否有任何内容阻止 std::string` 基类具有虚函数。
    【解决方案2】:

    这是一个奇特的想法:假设您的类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);
    

    当然,在构造函数中将所有成员初始化为零会更干净,但也许您有自己的原因不想创建自定义构造函数。

    【讨论】:

      【解决方案3】:

      将 std::string 成员归零是一个非常糟糕的主意,它会导致内存泄漏!千万不要这样做!

      【讨论】:

      • 多年来,这个问题已经得到了更详细的回答。这对讨论没有任何帮助。
      • 是的,但我花了 2 个小时找出泄漏的位置。我认为,人们知道它会导致泄漏会很有趣
      • 说法不正确。这里不需要符合要求的实现导致泄漏。事实上,语言规范根本没有承诺关于行为应该是什么。因此行为是未定义的。泄漏内存是未定义行为的一种有效形式,就像泄漏内存是一种有效形式一样。
      猜你喜欢
      • 1970-01-01
      • 2017-10-21
      • 2018-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-26
      相关资源
      最近更新 更多