简体   繁体   English

我可以删除使用 memcpy() 复制的 class 指针吗?

[英]Can I delete class pointer copied using memcpy()?

Is the following snippet of code valid?以下代码片段是否有效?

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?
    }
};

You can't copy classes using memcpy .您不能使用memcpy复制类。 And memcpy is just copying memory, not allocating anything.memcpy只是复制 memory,而不是分配任何东西。

You haven't actually allocated anything for pb .您实际上没有为pb分配任何东西。 If you allocate it with new , then using delete in the destructor is perfectly valid.如果你用new分配它,那么在析构函数中使用delete是完全有效的。

But why oh why are you doing a memcpy ?但是为什么哦,你为什么要做一个memcpy You should be using the copy constructor of the class and letting it copy itself in the appropriate fashion.您应该使用 class 的复制构造函数并让它以适当的方式复制自身。 The only time a memcpy would be remotely acceptable is when the class is a simple struct of POD types.唯一可以远程接受 memcpy 的情况是 class 是 POD 类型的简单结构。

It's valid, as in it will compile.它是有效的,因为它会编译。 But it is stricken with errors.但它充满了错误。 You never allocated any memory, so you'd need to do that first.您从未分配过任何 memory,因此您需要先执行此操作。 But there is absolutely no reason to use memcpy, and in most cases, it does the wrong thing.但是绝对没有理由使用 memcpy,而且在大多数情况下,它会做错事。 Just do this:只需这样做:

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

Or better yet, use a smart pointer, and you don't have to worry about deleting.或者更好的是,使用智能指针,您不必担心删除。 Or better yet, don't use a pointer at all if you retain sole ownership of the object.或者更好的是,如果您保留 object 的唯一所有权,则根本不要使用指针。

This code snippet is wrong because you can't call delete without calling to new for allocation of memory.这个代码片段是错误的,因为你不能在不调用new分配 memory 的情况下调用delete

Also your memcpy call can cause segmentation fault in most cases, because you are copying to unintialized pointer.此外,在大多数情况下,您的memcpy调用可能会导致分段错误,因为您正在复制到未初始化的指针。 You should allocate memort for SomeClass pointer before calling to memcpy .在调用memcpy之前,您应该为SomeClass指针分配内存。

Using memcpy with anything other than POD structures/objects ("plain old data"--things with no non-default constructors or destructors, and with virtual methods) is a recipe for disaster.将 memcpy 与 POD 结构/对象(“普通旧数据”——没有非默认构造函数或析构函数以及虚拟方法的事物)以外的任何东西一起使用是灾难的根源。 If you fix your program so that you're using memcpy to copy a POD structure which contains an "ordinary" pointer to a class item, any pointers copied as part of that structure must be handled the same as pointers copied via other means.如果您修复程序以便使用 memcpy 复制包含指向 class 项的“普通”指针的 POD 结构,则作为该结构的一部分复制的任何指针必须与通过其他方式复制的指针一样处理。 Exactly one copy (or the original) of any such pointer must be "deleted"--no more and no less.必须“删除”任何此类指针的确切副本(或原始副本)——不多也不少。 If you copy the pointer and abandon the original without calling "delete" on it, you should then call "delete" on exactly one copy.如果您复制指针并放弃原始指针而不对其调用“delete”,那么您应该只在一个副本上调用“delete”。

In general, one should avoid using memcpy in C++;一般来说,应该避免在 C++ 中使用 memcpy; in C, structures never had any "hidden" information which could be left in an inconsistent state by memcpy, but in C++ they often do (with the exception of POD structures).在 C 中,结构从来没有任何“隐藏”信息,这些信息可能会被 memcpy 留在不一致的 state 中,但在 C++ 中,它们经常这样做(除了 POD 结构)。 Although C++ is designed to be mostly compatible with C, the fact that something is legal in C does not mean that it is proper in C++. Although C++ is designed to be mostly compatible with C, the fact that something is legal in C does not mean that it is proper in C++.

You haven't allocated memory for that pointer using new , so you absolutely shouldn't be using delete on it.您尚未使用new为该指针分配 memory ,因此您绝对不应该在其上使用delete memcpy isn't allocating any memory for you. memcpy没有为您分配任何 memory。

Specifically, the only pointers you should be invoking delete on are pointers that have previously been returned by new , or a null pointer.具体来说,您应该调用delete的唯一指针是以前由new返回的指针,或 null 指针。 To use delete on any other pointer is undefined behaviour, according to the C++03 standard, 3.7.3.2/3-4.根据 C++03 标准 3.7.3.2/3-4,对任何其他指针使用delete是未定义的行为。

The value of the first argument supplied to one of the deallocation functions provided in the standard library may be a null pointer value;提供给标准库中提供的一个释放函数的第一个参数的值可能是 null 指针值; if so, the call to the deallocation function has no effect.如果是这样,对释放 function 的调用无效。 Otherwise, the value supplied to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(size_t) or operator new(size_t, const std::nothrow_t&)否则,提供给标准库中 operator delete(void*) 的值应是先前调用 operator new(size_t) 或 operator new(size_t, const std::nothrow_t&) 返回的值之一

...[snip]... ...[剪辑]...

The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined.)使用无效指针值(包括将其传递给释放函数)的效果是未定义的。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM