【问题标题】:Error Within Overloaded Assignment Operator Function and Copy Constructor重载赋值运算符函数和复制构造函数中的错误
【发布时间】:2019-10-12 01:06:52
【问题描述】:

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

当我第二次尝试调用我的赋值运算符时,我收到一个名为“munmap_chunk(): invalid pointer”的错误。如果我调用它一次,则不会显示错误。我是否正确编写了我的复制构造函数和赋值运算符?如果需要任何信息,我很乐意提供,谢谢。

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

【问题讨论】:

  • 你是delete[]ing arr,然后在下面的循环中立即使用arr[i] 对其进行索引。这会导致未定义的行为。
  • 如果你写了一个析构函数,你的赋值操作符如果你使用“复制/交换”就不需要那么复杂了。事实上,这很简单——只需 5 行 std::swap 行——无需分配内存,无需删除内存,一切都会正常进行。

标签: c++


【解决方案1】:

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

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

如果你写了一个拷贝构造函数(你有)和一个析构函数(你没有展示,但假设你做了),并且这两个函数都没有错误,那么赋值运算符可以实现简单地使用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 的销毁工作)。

【讨论】:

    猜你喜欢
    • 2014-10-12
    • 2023-03-29
    • 2013-10-23
    • 2012-03-01
    • 2019-11-23
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    相关资源
    最近更新 更多