0

我正在尝试在 C++ 中为一个对象实现一个 operator=,该对象具有一个指向用户定义类型的指针作为成员,该类型也分配了动态内存。

因此,鉴于下面的代码,如何为 B 实现正确的 operator=?我所追求的是如何将 A 中的动态内存复制到新的 B 对象中?

任何帮助将非常感激。

谢谢

class A
{
  int a;
  int* b;

  public:
    A()
    {
      a = 1;
      b = new int [20];
    }
};  

class B
{
  A* a;

  public:
  B()
  {
    a = new A;
  }
}
4

2 回答 2

1

对于初学者,您应该至少为类 A 定义复制构造函数、复制赋值运算符和析构函数。然后为类 B 定义复制赋值运算符很简单。

例如

#include <iostream>
#include <algorithm>

class A
{
    static const size_t N = 20;
    int a;
    int* b;

public:
    A()
    {
      a = 1;
      b = new int [N]();
    }

    A( const A &a ) : a( a.a ), b( new int [N] )
    {
        std::copy( a.b, a.b + N, this->b );
    }

    A & operator =( const A &a )
    {
        if ( &a != this )
        {
            this->a = a.a;

            int *p = new int[N];

            std::copy( a.b, a.b + N, p );

            delete [] this->b;
            this->b = p;
        }

        return *this;
    }

    ~A()
    {
        delete []b;
    }
};  

class B
{
  A* a;

  public:
  B() : a( new A )
  {
  }

  // copy constructor

  ~B()
  {
    delete a;
  }

  B & operator =( const B &b )
  {
    if ( this != &b )
    {
        *this->a = *b.a;
    }

    return *this;
  }
};

int main()
{
    B b1;
    B b2;

    b1 = b2;
}

请注意,在复制赋值运算符中,首先创建了一个新数组,然后再删除旧数组。这允许在发生异常时保持可分配对象的稳定状态。

于 2019-07-19T11:27:50.173 回答
0

首先:看看三法则,在特定情况下是绝对必须的。也考虑一下五规则,虽然不是强制性的,但你会遗漏一个很好的优化机会......

析构函数现在delete[]将是数组(这部分留给您......),然后复制构造函数将执行此操作:(深度)复制数据:

A::A(A const& other)
   : a(other.a), b(new int[20]) // assuming you have a fixed size for those arrays;
                                // better: introduce a constant for to avoid magic
                                // numbers in code!
{
    // you created a new array, but yet need to fill it with the others value
    std::copy(other.b, other.b + 20, b);
}

好的,第一步。使用复制和交换习语,赋值运算符变得非常简单:

A& operator=(A other) // YES, no reference! This will invoke the copy (or move!)
                      // constructor of your class!
{
    swap(*this, other); // you'll need to implement it yet!
    return *this;
    // at this point, the destructor of other will clean up data that was potentially
    // contained in *this before...
}

最后是移动构造函数:

A::A(A&& other)
   : a(0), b(nullptr)
{
    swap(*this, other);
    // again swapping??? well, sure, you want the data from other to be contained
    // in *this, and we want to leave other in some kind of valid state, which the
    // nullptr is fine for (it's fine to delete[] a null pointer, so you don't even
    // need to check in the destructor...) 
}

现在由你决定:class B类似地......

旁注:使用智能指针std::unique_ptrstd::unique_ptr)。

于 2019-07-19T11:41:45.617 回答