21xrx.com
2024-09-20 06:07:37 Friday
登录
文章检索 我的文章 写文章
C++对象赋值实现方法详解
2023-06-27 21:30:38 深夜i     --     --
C++ 对象赋值 实现方法 详解

C++是一门面向对象的编程语言,对象的赋值是程序设计中非常常见的操作,也是操作对象的基本方法之一。在C++中,实现对象的赋值主要有三种方法:浅拷贝、深拷贝和移动语义。

浅拷贝(Shallow Copy)

浅拷贝是将源对象的内存地址复制给目标对象,并没有将源对象的成员变量逐一复制到目标对象中。因此,在进行浅拷贝时,源对象和目标对象共享同一个内存地址,当某一个对象改变其中的成员变量时,另一个对象也会跟着改变。这种做法可以用于复制简单的对象,但是对于复杂对象来说显然是不可行的。如下面的代码实现了浅拷贝:


class Student {

public:

  Student(char* name, int age):name_(name), age_(age) {}

  char* name_;

  int age_;

};

int main()

{

  Student s1("Li Lei", 18);

  Student s2 = s1;  //浅拷贝

  cout << "s1.name_:" << s1.name_ << ",s1.age_:" << s1.age_ << endl;

  cout << "s2.name_:" << s2.name_ << ",s2.age_:" << s2.age_ << endl;

  s1.name_ = "Han Meimei";

  s2.age_ = 20;

  cout << "s1.name_:" << s1.name_ << ",s1.age_:" << s1.age_ << endl;

  cout << "s2.name_:" << s2.name_ << ",s2.age_:" << s2.age_ << endl;

  return 0;

}

在上面的代码中,我们定义了一个Student类,有字符型指针name_和整型变量age_两个成员变量,然后在main函数中创建了两个对象s1和s2,其中s2通过浅拷贝的方式来实现,接着修改了s1的name_和s2的age_。最终的输出结果如下:


s1.name_:Li Lei,s1.age_:18

s2.name_:Li Lei,s2.age_:18

s1.name_:Han Meimei,s1.age_:18

s2.name_:Li Lei,s2.age_:20

从结果可以看出,s1的name_被修改了,s2的age_也被修改了。这表明,当一个对象的成员变量被修改,另一个对象也会跟着改变,这种情况下另一个对象丢失了它的数据,这是一种非常严重的问题。

深拷贝(Deep Copy)

深拷贝是将源对象的每个成员变量逐一复制到目标对象里面去,这种方式相对于浅拷贝会增加更多的复制过程。由于每个子对象都需要递归地调用拷贝构造函数,因此深拷贝的实现比较复杂。在深拷贝中,每个对象都有着它独立的内存地址,修改一个对象的成员变量,不会影响另一个对象的成员变量。下面的代码演示了深拷贝的实现方法:


class Student {

public:

  Student(char* name, int age):name_(new char[strlen(name)+1]), age_(age) {

    strcpy(name_, name);

  }

  Student(const Student& stu):name_(new char[strlen(stu.name_)+1]), age_(stu.age_) {

    strcpy(name_, stu.name_);

  }

  ~Student() { delete[] name_; }

  char* name_;

  int age_;

};

int main()

{

  Student s1("Li Lei", 18);

  Student s2 = s1;  //深拷贝

  cout << "s1.name_:" << s1.name_ << ",s1.age_:" << s1.age_ << endl;

  cout << "s2.name_:" << s2.name_ << ",s2.age_:" << s2.age_ << endl;

  s1.name_ = "Han Meimei";

  s2.age_ = 20;

  cout << "s1.name_:" << s1.name_ << ",s1.age_:" << s1.age_ << endl;

  cout << "s2.name_:" << s2.name_ << ",s2.age_:" << s2.age_ << endl;

  return 0;

}

在上述代码中,需要注意两个地方。首先,我们在Student的构造函数和拷贝构造函数中分别为成员变量name_动态分配内存,并进行深度拷贝。其次,在Student类的析构函数中要注意释放动态分配的内存。

移动语义(Move Semantics)

C++11引入了移动语义(move semantics)的概念,对于临时对象、右值引用等的语义进行定义和处理。移动语义允许对象的内存资源所有权在程序的执行中被传递或者转移。这样,在复制对象时,就可以将原来对象的资源转移到新建的对象中,避免了深拷贝产生的不必要开销。下面是移动语义的实现方式:


class Student {

public:

  Student(char* name, int age):name_(name), age_(age) {}

  Student(Student&& temp):name_(temp.name_), age_(temp.age_) {

    temp.name_ = nullptr;

  }

  char* name_;

  int age_;

};

int main()

{

  Student s1("Li Lei", 18);

  Student s2 = std::move(s1); //移动语义

  cout << "s1.name_:" << s1.name_ << ",s1.age_:" << s1.age_ << endl;

  cout << "s2.name_:" << s2.name_ << ",s2.age_:" << s2.age_ << endl;

  s2.name_ = "Han Meimei";

  cout << "s1.name_:" << s1.name_ << ",s1.age_:" << s1.age_ << endl;

  cout << "s2.name_:" << s2.name_ << ",s2.age_:" << s2.age_ << endl;

  return 0;

}

在上述代码中,我们定义了一个移动构造函数,并使用std::move进行了移动操作。移动构造函数接受的参数是一个右值引用,可以避免进行深度拷贝。从输出结果可以发现,s1.name_为nullptr,说明成功的将内存资源移动到了s2中。

总结

在C++中,实现对象的赋值有三种方式:浅拷贝、深拷贝和移动语义。浅拷贝是将原有对象直接赋值给新建对象,新旧对象共享一个内存地址;深拷贝是将原有对象的每个成员变量逐一复制到新建对象中去,每个对象都有它独立的内存地址;移动语义是将内存资源的所有权从一个对象转移到另一个对象。在不同的场景下,选择不同的方法进行对象赋值可以更好的解决实际编程问题。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复