重载的赋值运算符函数和副本构造函数中的错误

时间:2019-10-12 01:06:52

标签: c++

我目前正在编写一个创建动态分配的循环数组的程序。为此,我创建了一个复制构造函数和一个赋值运算符。

当我尝试第二次调用赋值运算符时,出现错误消息“ munmap_chunk():无效指针”。如果我调用一次,则不会显示错误。我是否在正确编写拷贝构造函数和赋值运算符?如果有需要我高兴提供的信息,谢谢。

CircularDynamicArray(const CircularDynamicArray& source){
    cout << "copy constructor called" << endl;
    m_capacity = source.m_capacity;
    m_size = source.m_size;
    m_front = source.m_front;
    m_rear = source.m_rear;
    arr = new elmtype[source.m_capacity];
    for(int i = 0; i < source.m_capacity; i++) {
        arr[i] = source.arr[i];
    }
}
//overloaded assignment operator
CircularDynamicArray &operator = (const CircularDynamicArray& source) {
    cout << "Overloaded Assignment called" << endl; 
    //check for self assignment
    if (this == &source) {
        return *this;
    }
    m_capacity = source.m_capacity;
    m_size = source.m_size;
    m_front = source.m_front;
    m_rear = source.m_rear;    
    delete[]arr;
    for(int i = 0; i < source.m_capacity; i++) {
        arr[i] = source.arr[i];
    }
    return *this;
}

1 个答案:

答案 0 :(得分:0)

  

我是否正确编写了复制构造函数和赋值运算符?

我会说,在编写赋值运算符时,您将为自己做更多的工作。

如果您已经编写了一个复制构造函数(您拥有)和一个析构函数(您没有显示,但假设您已经编写了),并且这两个函数都没有错误,那么可以实现赋值运算符简单地使用copy / swap

通常,您应该努力在编写赋值运算符之前先编写复制构造函数和析构函数,以便可以利用编写赋值运算符的“技巧”。这是一个示例:

#include <algorithm>
//...
CircularDynamicArray &operator=(const CircularDynamicArray& source) 
{
  if (this != &source) 
  {
      CircularDynamicArray temp(source);    // Create a copy of what we want
      // get the temp's innards, and give temp our stuff
      std::swap(temp.m_capacity, m_capacity);
      std::swap(temp.m_size, m_size);
      std::swap(temp.m_front, m_front);
      std::swap(temp.m_rear, m_rear);
      std::swap(temp.arr, arr);
  }  // goodbye temp

  return *this; 
}

没有分配内存,没有delete[]调用,您甚至不需要检查自我分配(但是为了提高效率,无论如何都要这样做)。以上也是异常安全的。赋值运算符工作所需的一切,基本上都是完美无缺的。

请注意,您需要交换所有个成员变量-不要忘记任何成员变量,因为这将导致其无法正常工作。

要做的就是创建一个传入对象的副本,并用副本替换当前对象this的内脏。然后,副本将与您的旧信息一起消失。这就是为什么您需要一个工作副本构造函数(用于source的初始复制才能工作)和一个工作析构函数(以使temp的销毁有效)的原因。