【问题标题】:Could I use memcpy to the pointer which I new it before?我可以使用 memcpy 指向我之前 new 的指针吗?
【发布时间】:2023-03-24 08:37:01
【问题描述】:

例如,我尝试写自己的vector,所以我就这样写它的assign函数

template <typename T>
void Vector<T> :: assign(T *start, T *end)
{
    if (end - start > _capacity)
    {
        resize(end - start);
    }
    _size = end - start;
    delete []ptr;
    ptr = new T[_capacity];
    memcpy(ptr, start, end - start);
}

我之前有新的指针ptr,但我可以复制指针startend之间的所有内容

为什么?非常感谢。

【问题讨论】:

  • 仅当 T 是可简单复制的类型时...(读作:不,坏主意。)
  • this answer
  • 这不提供强异常保证。

标签: c++ pointers memcpy


【解决方案1】:

第一个问题是这只适用于简单类型(读取 POD)。
任何带有构造函数/析构函数的东西都需要调用它们。

其次,这不是异常安全的。
连最基本的保障都没有,更何况是强有力的保障。

您需要在修改对象之前完成所有异常不安全的工作。这意味着new 必须在您修改对象之前完成(并且绝对是在免费之前)。否则,您可能会抛出使对象处于无效状态(这可能看起来不错,但是如果您捕获异常并继续,您现在有一个包含指向已释放内存的指针的对象)。

因此,即使您使用std::copy(),您仍然做错了事。
我个人认为 std::copy() 的建议是红鲱鱼。它会正确地复制数据,但你的方法仍然很糟糕。您需要在复制和交换 idium 上使用扭曲。

template <typename T>
void Vector<T> :: assign(T *start, T *end)
{
    Vector<T> tmp(start, end);  // construct a temp object that allocates the memory.



    swap(tmp);                  // Swap the current object and the tmp objects data.
                                // When the tmp object goes out of scope it will delete
                                // what was the current objects data

}

【讨论】:

    【解决方案2】:

    以这种方式重用指针完全没问题,但是在这里使用 memcpy 是安全的,因为你不知道 T 是什么类型。如果 T 是字符串或向量之类的对象类型,则会导致未定义的行为。

    要解决此问题,请将行更改为

    std::copy(start, end, ptr);
    

    这是安全的 C++ 方法。

    希望这会有所帮助!

    【讨论】:

    • 谢谢,我刚刚发现正确的使用方法是std::copy(start, end, ptr);
    • 这不是一个好主意。因为它仍然留下 assign() 方法不提供异常保证,因此它是一个错误的答案。
    • std::copy 的 args 顺序不正确。它应该是std::copy(start, end, ptr);,而不是std::copy(ptr, start, end);。在 C++11 中,您可以使用std::copy_n(start, _size, ptr)
    • @LokiAstari- 绝对。但是,鉴于 OP 的问题仅限于这一行,我决定将我的答案集中在解释为什么 memcpy 是一个坏主意。将整个函数重写为异常安全会分散该特定教学点的注意力。
    猜你喜欢
    • 1970-01-01
    • 2011-01-17
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    • 2015-06-17
    • 2019-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多