1

我正在尝试实现我的容器 Vector 以用于教育目的。
在实现它的方法reserve时,我遇到了一个问题:
这是将元素数组从内存中的一个位置(初始容量)重定位到分配给新容量的内存的最佳方式吗?
我考虑了 2 种可能性:使用循环或使用 c 函数memcpy
这是我的实现:

template <typename T>
void MyVector<T>::reserve(int elements) 
{
    if (m_size >= elements) // when no need to reserve memory as at least demanded amount of memory has been already allocated
        return;
    m_capacity = elements;
    tmp = m_array;
    // allocate needed amout of memory:
    m_array = new T[elements];
    // copy elements ???? can I use memcpy????
    for (int i = 0; i < m_size; ++i)
    {
        m_array[i] = tmp[i];
    }
    delete tmp;
}

template <typename T>
void MyVector<T>::reserve1(int elements) 
{
    if (m_size >= elements) // when no need to reserve memory as at least demanded amount of memory has been already allocated
        return;
    m_capacity = elements;
    tmp = m_array;
    // allocate needed amout of memory:
    m_array = new T[elements];
    // copy elements ???? can I use memcpy????
    memcpy(m_array, tmp, m_size);
    delete [] tmp;
}

问题: - 我应该考虑哪些瓶颈?
- 性能上有什么不同?
- 有没有更有效的方法?
- 您能否建议我的信息来源,其中深入描述了 STL 容器的实施(我的目标是进行自己的实施,并与专业实施进行比较,以检查我的知识并找出需要改进的领域)

4

3 回答 3

5

您不能使用memcpy,因为重要的对象可能包含指向其他内存块的指针。

考虑一个向量std::string: 每个通常都实现为一个小对象,其中包含一个指向动态分配的字符数组的指针。如果你memcpy是字符串,你会复制指针而不是它们的实际字符数据。但是这些指针的所有权不会转移。因此,当您删除原始数组(为所有这些字符串调用析构函数)时,它们的内存被释放,并且您的“新”对象都有悬空指针。

使用std::copy是实现这一目标的更好方法。

于 2013-03-21T21:54:57.663 回答
1

在性能方面以及使用memcpy“简单循环”方法复制对象会产生影响的其他因素。例如:

class Blah
{
    Blah()
    {
        some_function(this);
    }
};

MyVector<Blah> v;

... 

现在,如果以某种方式some_function存储this[无论出于好坏原因],您reserve1将导致它被删除,但对的引用this仍将指向已删除的对象。这可能不是你想要的。

如果对象包含任何在内部使用分配的对象,当然同样适用——例如std::string

于 2013-03-21T21:56:58.553 回答
0

我同意罗迪的观点。但更糟糕的是。即使您设法在不调用析构函数的情况下释放旧内存并且未释放其他内存,某些对象也可能包含指向内部部分的引用或指针,无论如何都会被破坏。最后,最好知道新内存对齐的后果。(对于 T=char,memcpy 可能是最好的)。

如果可行,则强制执行移动任务for可能是最好的解决方案。(你不需要旧的副本)

好吧,最终您可以看到 std::vector 是如何设计的,具有单独的内存分配,未初始化,然后就地初始化,复制或移动。查看 Stroustrup 的 The C++ Programming Language, Third Edition 中的 19.4 Allocators。

于 2013-03-21T22:11:18.857 回答