【问题标题】:Deep copy and assignment overload and std::swap深拷贝和赋值重载和 std::swap
【发布时间】:2018-05-09 18:19:39
【问题描述】:

实际上我现在有 2 个单独的问题,所以我将这个问题分为 2 个部分。第一个是关于深拷贝和赋值运算符重载

首先,我的班级标题

template <class T>
class MyVector{    
    std::unique_ptr<T[]> p_array;
    int p_size; 
    int p_capacity; 
public: 
    MyVector();
    MyVector(const MyVector&);
    MyVector& operator= (const MyVector&);
}

这是我的复制构造函数和赋值运算符重载函数

template <class T>
MyVector<T>::MyVector(const MyVector &source) {
    p_capacity = source.p_capacity;
    p_size = source.p_size;
    p_array = std::make_shared<T[]>(p_capacity);
    for(int i = 0; i < p_capacity; i++) {
        p_array[i] = source.p_array[i];
    }
}

template <class T>
MyVector& MyVector<T>::operator=(const MyVector &source) {
    if(this == &source) return *this;

    p_capacity = source.m_capacity;
    p_size = source.m_size;

    p_array = std::make_unique<T[]>(p_capacity);
    for(int i = 0; i < p_capacity; i++) {
        p_array[i] = source.p_array[i];
    }
}

在主要

int main() {
MyVector<int> vecA;
//adding elements to vecA
MyVector<int> vecB(vecA);
}

不幸的是我得到的是

g++ -std=gnu++14 -static-libstdc++ -g3 -Icode/include -c 代码/源/my_vector.cpp -o obj/my_vector.o 代码/源/my_vector.cpp:20:1:错误:无效使用模板名称 没有参数列表的“MyVector” MyVector& MyVector::operator=(const MyVector &source) { ^ Makefile:29: 目标“obj/my_vector.o”的配方失败 make: *** [obj/my_vector.o] 错误 1

第 2 部分

在同一个类中,我得到了 extendArray() 函数,如果调用该函数,则将数组容量扩展 2 并将所有元素从旧数组复制到新数组。我尝试使用 for 循环遍历所有元素,它工作得很好,但我想改用 std::swap ,然后我遇到了一些奇怪的麻烦。

template <class T>
void MyVector<T>::extendArray() {
    p_capacity *= 2;
    std::unique_ptr<T[]> temp_array = std::make_unique<T[]>(p_capacity/2);
    std::swap(p_array, temp_array);
    p_array.reset();
    p_array = std::make_unique<T[]>(p_capacity);
    std::swap(temp_array, p_array);
}

我只是这样做

int main(){
        MyVector<int> test;
        test.pushBack(5);
        test.pushBack(10);
        test.pushBack(15);
        test.pushBack(20);
        test.pushBack(25);     

        for(int i = 0; i < test.getCapacity(); i++) {
            cout << test[i] << ", ";
        }  
    }

我希望看到以下输出(添加第 4 个元素后,将调用 extendArray() 函数并将容量从 4 扩展到 8)
5、10、15、20、25、0、0、0
当我使用基于 for 循环的旧 extendArray() 函数时,我得到了它,但如果我使用 std::swap 函数,我得到
5、10、15、20、25、0、1041、0
我不知道这个 1041 是从哪里来的。更重要的是,valgrind 在 4 个这样的上下文中显示 9 个错误:

==5967== 大小为 4 的无效写入
==5967== 在 0x403000: MyVector::pushBack(int const&)
(my_vector.cpp:17)
==5967== by 0x402CE7: main (main.cpp:11)
==5967== 地址 0x542bc88 是在一个大小为 8 的块分配后的 0 个字节
==5967== 在 0x4C2DB8F:malloc(在 /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so 中)
==5967== by 0x404707: operator new(unsigned long) (in /home/maciek/Programming/MyVector/MyVector)
==5967== by 0x403968: operator new[](unsigned long) (in /home/maciek/Programming/MyVector/MyVector)
==5967== by 0x40314B: std::_MakeUniq::__array std::make_unique(unsigned long) (in /home/maciek/Programming/MyVector/MyVector)
==5967== by 0x402F3C: MyVector::MyVector() (my_vector.cpp:6)
==5967== by 0x402C99: main (main.cpp:8)
==5967==

【问题讨论】:

  • 关于第 1 部分:您试图在复制构造函数中将 shared_ptr 分配给 unique_ptr。
  • 是的,它也应该是复制构造函数中的 make_unique 。不过,和以前一样的错误。没有参数列表的模板名称“MyVector”的使用无效。
  • 在赋值运算符实现中,您应该将返回类型指定为 MyVector 而不是 MyVector。
  • 是的,我也是这么想的。第 1 部分还好,第 2 部分仍然不知道如何移动。
  • extendArray 完全没有意义。这是一个精心设计的无操作:p_array 最终持有与它开始时完全相同的指针(嗯,不完全是无操作:p_capacity 现在持有一个与实际容量不匹配的值)。我不确定我是否理解你想用它来实现什么,但不管它是什么,这个函数都不会那样做。

标签: c++11 templates swap unique-ptr deep-copy


【解决方案1】:

重点是将所有元素 from_array 复制到临时数组中,为 m_array 分配新的更大的大小(容量),然后将临时数组中的元素复制回 m_array。我通过以下代码找到了解决方案:

template <class T>
void MyVector<T>::extendArray() {
    m_capacity *= 2;
    std::unique_ptr<T[]> temp_array = std::move(m_array);
    m_array = std::make_unique<T[]>(m_capacity);
    std::copy(temp_array.get(), temp_array.get() + m_capacity/2, m_array.get());        
}

工作得很好。 pushBack() 方法没有显示在上面的代码中,因为它与我的问题无关,它只是检查是否有足够的空间容纳新元素(如果没有,则调用 extendArray())并在末尾添加这个元素数组。

【讨论】:

    猜你喜欢
    • 2010-11-01
    • 2012-04-12
    • 2013-06-19
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    • 2016-05-07
    相关资源
    最近更新 更多