【问题标题】:Can I delete class pointer copied using memcpy()?我可以删除使用 memcpy() 复制的类指针吗?
【发布时间】:2011-04-28 14:50:22
【问题描述】:

下面的sn-p代码有效吗?

class Foo
{
public:
    int a;
    SomeClass* pb;

    Foo() {...}
    Foo(const Foo& rhs)
    {
         this->a = rhs.a;
         memcpy(this->pb, rhs.pb, sizeof(SomeClass));
    }
    ~Request()
    {
        delete this->pb; // Suppose pb is a result of copy constructor,
                         // Is this valid or is there a better way?
    }
};

【问题讨论】:

    标签: c++ memcpy


    【解决方案1】:

    您实际上没有为pb 分配任何东西。如果你用new分配它,那么在析构函数中使用delete是完全有效的。

    但是为什么哦,你为什么要做memcpy?您应该使用类的复制构造函数并让它以适当的方式复制自身。 只有当类是 POD 类型的简单结构时才可以远程接受 memcpy。

    【讨论】:

    • 我之所以要使用 memcpy 的原因是因为 pb 实际上是一个指向 SomeClass 派生类的指针。 SomeClass 及其派生类不在我的控制之下,而 Foo 可能不知道 pb 的确切类型。您对这个问题有什么建议吗?
    • 你不能使用memcpythis->pb = new SomeClass(*rhs.pb); 怎么了?
    • @Let_Me_Be:如果我们不知道 rhs.pb 的确切类型是否有效?它可能是SomeClassWhichIsDerivedFromSomeClass 的类型
    • @avee 复制SomeClass时这无关紧要。
    • @avee 看到这个话题:stackoverflow.com/questions/5731217/…
    【解决方案2】:

    您不能使用memcpy 复制课程。而memcpy 只是复制内存,而不是分配任何东西。

    【讨论】:

    • 另外,使用“memcpy”复制内存,没有新的分配,会导致内存问题(双重释放等),在使用对象和释放它的正常速度下。建议使用copy-constructors方式。
    【解决方案3】:

    它是有效的,因为它会编译。但它充满了错误。您从未分配任何内存,因此您需要先执行此操作。但是绝对没有理由使用 memcpy,而且在大多数情况下,它会做错事。只需这样做:

    Foo(const Foo& rhs)
        :a(rhs.a),
         pb(new SomeClass(*rhs.pb))
    {    
    }
    

    或者更好的是,使用智能指针,您不必担心删除。或者更好的是,如果您保留对象的唯一所有权,则根本不要使用指针。

    【讨论】:

    • 这是一个很好的方法,但它并不能解决我遇到的实际问题,请参阅我对@Mark Ransom 回答的评论
    【解决方案4】:

    这个代码 sn-p 是错误的,因为你不能在不调用 new 的情况下调用 delete 来分配内存。

    在大多数情况下,您的memcpy 调用可能会导致分段错误,因为您正在复制到未初始化的指针。在调用memcpy 之前,您应该为SomeClass 指针分配内存。

    【讨论】:

      【解决方案5】:

      将 memcpy 与 POD 结构/对象(“普通旧数据”——没有非默认构造函数或析构函数的东西,以及虚拟方法)以外的任何东西一起使用是灾难的根源。如果您修复程序以便使用 memcpy 复制包含指向类项的“普通”指针的 POD 结构,则作为该结构的一部分复制的任何指针必须与通过其他方式复制的指针相同的处理方式。必须“删除”任何此类指针的确切副本(或原始副本)——不多也不少。如果您复制指针并放弃原始指针而不对其调用“delete”,则应仅在一个副本上调用“delete”。

      一般来说,应该避免在 C++ 中使用 memcpy;在 C 中,结构从来没有任何“隐藏”信息,这些信息可能会被 memcpy 置于不一致的状态,但在 C++ 中,它们经常这样做(POD 结构除外)。尽管 C++ 被设计为与 C 大部分兼容,但某些东西在 C 中是合法的这一事实并不意味着它在 C++ 中是正确的。

      【讨论】:

        【解决方案6】:

        您还没有使用new 为该指针分配内存,因此您绝对不应该在其上使用deletememcpy 没有为你分配任何内存。

        具体来说,您应该调用delete 的唯一指针是先前由new 返回的指针,或空指针。根据 C++03 标准 3.7.3.2/3-4,在任何其他指针上使用 delete 是未定义的行为。

        第一个参数的值 提供给其中一个解除分配 标准中提供的功能 library 可能是一个空指针值; 如果是这样,调用释放 功能没有效果。 否则, 提供给操作员的值 标准库中的 delete(void*) 应该是返回的值之一 先前的调用 运算符 new(size_t) 或运算符 新的(size_t, const std::nothrow_t&)

        ...[剪辑]...

        使用无效指针的影响 值(包括将其传递给 释放函数)是 未定义。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-24
          • 2011-03-02
          • 2021-05-07
          • 1970-01-01
          • 2011-06-12
          • 2020-02-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多