复制构造函数和动态分配的数组

Copy constructor and dynamically allocated array

本文关键字:数组 动态分配 构造函数 复制      更新时间:2023-10-16

我将保持它简短和清晰-为了练习动态分配内存,我决定做一个圆圈,我将在一个动态分配的数组中存储它的参数(中心和半径长度的X和Y)。由于数组是动态分配的,这意味着为了阻止泄漏,我必须实现构造函数。这也意味着为了避免其他一些bug,我需要实现一个复制构造函数并重载赋值操作符。(使用几乎相同的代码)我认为我已经相当好地实现了析构函数。不过,对于复制构造函数,我确实需要一些帮助。

#include <iostream>
using namespace std;
class Circle
{
private:
    int* data;
public:
    Circle(){
        cout <<"I am the default constructor" << endl;
        data = NULL;
    }
    Circle(int* p){
        cout <<"I am the set up constructor" << endl;
        data = p;
    }
    ~Circle(){
        cout <<"I am the destructor" << endl;
        delete data;
    }
    Circle& operator=(const Circle& tt1){
        cout << "Overloaded assignment operator reporting in!" << endl;
        if(this != &tt1){
            //free old data
            delete this->data;
            data = new int(3);
           *data = *(tt1.get_data());
            *(arr+1) = *(tt1->get_data()+1);
            *(arr+2) = *(tt1->get_data()+2);
            return *this;
        }
    }
    Circle(const Circle& tt1){
        cout << "I am the copy constructor!" << endl;
        if(this != &tt1){
            //free old data
            delete this->data;
            data = new int(3);
           *data = *(tt1.get_data());
            *(arr+1) = *(tt1->get_data()+1);
            *(arr+2) = *(tt1->get_data()+2);
            return *this;
        }
    }
};
int main(){
    //is this object constructed well?
    int arr [] = { 16, 2, 7};
    Circle a(arr);
    return 0;
}
//is this object constructed well?
int arr [] = { 16, 2, 7};
Circle a(arr);

答案是"是"answers"不是":构造函数不复制数组,它只是复制指向数组第一个元素的指针。因此,如果不希望Circle类拥有数组,则不需要提供析构函数、复制构造函数或赋值操作符。

但是更可能的情况是,确实希望类拥有该数组,在这种情况下,您需要创建它的本地副本并存储它。要实现这一点,需要一个额外的信息:数组的大小,当传递给(并实现析构函数、复制构造函数、赋值操作符)接受指针的函数时,该信息将完全丢失。

Edit由于这是在输入数组总是大小为3的情况下动态分配的练习,因此这是构造函数接受数组的示例:

Circle(int* p)
{
  data = new int[3];
  std::copy(p, p+3, data); // UB if p doesn't point to an array of at least 3 elements
}
你需要在析构函数中调用delete[],因为你调用了new[]:
~Circle()
{
    delete [] data;
}

在实现赋值操作符时,考虑复制和交换习惯用法

我对你的做法写了一段正确的代码,希望对你有所帮助。我用tdm-gcc构建它,它运行得很好。

#include<iostream>
#include<algorithm> //std::copy
using namespace std;
class Circle {
private:
 int* data;
public:
 Circle(){
  cout <<"I am the default constructor" << endl;
  data = NULL;
 }
 Circle(int* p){
  cout <<"I am the set up constructor" << endl;
  data =new int[3];
  copy(p,p+3,data);
 }
 ~Circle(){
  cout <<"I am the destructor" << endl;
  if (data!=NULL) {
   delete[] data;
  }
 }
 Circle(const Circle& tt1){
  cout << "I am the copy constructor!" << endl;
  if (this != &tt1) {
   if (data!=NULL) {
    delete[] data;
   }
   data = new int[3];
   *data = *(tt1.get_data());
   *(data+1) = *(tt1.get_data()+1);
   *(data+2) = *(tt1.get_data()+2);
  }
 }
 Circle& operator=(const Circle& tt1){
  cout << "Overloaded assignment operator reporting in!" << endl;
  if (this != &tt1) {
   if (data!=NULL) {
    delete[] data;
   }
   data = new int[3];
   *data = *(tt1.get_data());
   *(data+1) = *(tt1.get_data()+1);
   *(data+2) = *(tt1.get_data()+2);
  }
 }
 int* get_data() const {
  return data;
 }
};
int main(){
 int arr[]={16,2,7};
 Circle a(arr);
 cout<<*a.get_data()<<'t'
 <<*(a.get_data()+1)<<'t'
 <<*(a.get_data()+2)<<endl<<endl;
 return 0;
}