📌  相关文章
📜  我们什么时候应该用C++编写自己的赋值运算符?(1)

📅  最后修改于: 2023-12-03 15:39:38.154000             🧑  作者: Mango

我们什么时候应该使用C++编写自己的赋值运算符?

在C ++中,赋值运算符(=)是一个预定义的运算符,用于将一个对象的值赋给另一个对象。当我们使用自定义的C ++类时,我们需要决定是否编写自己的赋值运算符,而不是使用默认的。下面是几种情况,我们应该考虑编写自定义赋值运算符的情况。

1. 当类中包含指向动态分配内存的指针时

如果一个类中有指向动态分配内存的指针,而我们只是使用默认赋值运算符,那么两个对象的指针将指向同一块内存,如果其中一个对象被删除,则另一个对象将指向已删除的内存,这可能会导致严重的后果。通过使用自定义赋值运算符,我们可以确保每个对象都拥有自己的内存,从而避免这种风险。

class MyClass{
private:
   int value;
   int* ptr;

public:
   MyClass(){
      value=10;
      ptr=new int(value);
   }

   //Custom copy constructor
   MyClass(const MyClass &obj) {
      value=obj.value;
      ptr=new int(value);
   }

   //Custom copy assignment operator
   MyClass& operator=(const MyClass &obj){
      if(this != &obj){//Check for self assignment
         value=obj.value;
         *ptr=*obj.ptr;
      }
      return *this;
   }

   //Destructor
   ~MyClass() {delete ptr;}
};
2. 当类中存在常量的成员变量时

如果在类中定义了常量的成员变量,则可能无法使用默认的赋值运算符,因为常量无法被重新赋值。为了避免编译错误,我们需要使用自定义赋值运算符来处理这种情况。

class MyClass{
private:
   const int value;

public:
   MyClass(int i):value(i) {}

   //Custom copy assignment operator
   MyClass& operator=(const MyClass &obj){
      //No need to check for self assignment since 'value' is const
      return *this;
   }
};
3. 当类中包含有资源的成员变量时

如果在类中定义了资源,如文件句柄或网络连接,那么我们需要确保这些资源在对象复制或分配期间得到妥善处理。使用自定义赋值运算符,我们可以确保这些资源得到适当的释放或复制。

class MyClass{
private:
   FILE* fp;

public:
   MyClass(){
      fp=fopen("file.txt","r");
      if(fp==nullptr){
         throw std::runtime_error("Unable to open file");
      }
   }

   //Custom copy assignment operator
   MyClass& operator=(const MyClass &obj){
      if(this != &obj){//Check for self assignment
         fp=fopen("file.txt","r");
         if(fp==nullptr){
           throw std::runtime_error("Unable to open file");
         }
      }
      return *this;
   }

   //Destructor
   ~MyClass() {fclose(fp);}
};

总的来说,我们应该在类中包含自定义赋值运算符的情况是在自己的类中实现动态分配内存,常量数据成员或类中包含资源等情况。 在这些情况下,重载赋值运算符可以确保正确地分配内存,保存常量的数据成员,并正确地处理资源。