拷贝构造函数与赋值构造函数
在C++中,如果要创建一个新的类,并用已有的类来给它附初值。就要用到拷贝构造函数,拷贝构造函数又分为两种。
1.合成的拷贝构造函数
在你没有定义自己的拷贝构造函数而又调用了拷贝构造函数时,编译器会调用合成的拷贝构造函数来进行赋值。合成的拷贝构造函数进行的拷贝叫做浅拷贝(又叫位拷贝)。在大多数情况下,使用合成的拷贝构造函数也不会出错。但要是你的类的数据成员中又指针或分配了内存。那合成的拷贝构造函数就不适用这种情况。
如下错误代码:
#include <iostream>
#include <string>
class Human {
public:
Human(int* age); //构造函数
~Human();
int describe() const; //输出age的值
int changeAge(); //改变age的值
private:
int* age;
};
Human::Human(int* age)
{
this->age = age;
}
Human::~Human()
{
}
int Human::describe() const
{
std::cout << *(this->age) << std::endl;
return 1;
}
int Human::changeAge()
{
int age = 10;
*(this->age) = age;
return 1;
}
int main(void) {
int age = 15;
Human human(&age); //构造函数
Human human1(human); //调用合成的拷贝构造函数
human.describe(); //改变前human的age值
human1.describe(); //改变前human1的age值
human.changeAge();
std::cout << "改变后" << std::endl;
human.describe(); //改变后human的age值
human1.describe(); //改变前human1的age值
system("pause");
return 0;
}
显然我们只想改变human的age值,但是却连human1的值也改变了。这并非我们的初衷。这是因为合成的拷贝构造函数进行的是位拷贝。在拷贝指针它会拷贝一个指针指向原来的那块内存,而不是开辟一块新的内存。这就导致了这种结果。
2.自定义的拷贝构造函数
自定义的拷贝构造函数就是我们自己定义的拷贝构造函数,可对类的数据成员赋值,也可开辟一块新的内存。防止浅拷贝的错误。叫做深拷贝。代码如下:
Human(const Human& human) {
this->age = new int;
*(this->age) = *(human.age);
}
成功运行:
3.赋值构造函数
赋值构造函数与拷贝构造函数类似,如果不自己定义,编译器会自动生成。赋值构造函数也存在浅拷贝的问题。所以应定义自己的赋值构造函数。再一个是赋值构造函数与拷贝构造函数的调用时机的区别。拷贝构造函数是在类定义的时候用另一个类进行赋值(创建与赋值是同时进行的)。而赋值构造函数是在类创建后使用=进行赋值的(创建与赋值不是同时进行的),因此自定义的赋值构造函数需要重载=进行定义。
代码如下:
Human operator=(Human& human) {
this->age = new int;
*(this->age) = *(human.age);
return *this;
}
完整代码实现:
#include <iostream>
#include <string>
class Human {
public:
Human(int* age); //构造函数
Human(const Human& human); //自定义的拷贝构造函数
Human operator=(Human& human); //赋值构造函数
~Human();
int describe() const; //输出age的值
int changeAge(); //改变age的值
private:
int* age;
};
Human::Human(int* age)
{
this->age = age;
}
Human::Human(const Human& human)
{
this->age = new int;
*(this->age) = *(human.age);
}
Human Human::operator=(Human& human)
{
this->age = new int;
*(this->age) = *(human.age);
return *this;
}
Human::~Human()
{
}
int Human::describe() const
{
std::cout << *(this->age) << std::endl;
return 1;
}
int Human::changeAge()
{
int age = 10;
*(this->age) = age;
return 1;
}
int main(void) {
int age = 15;
Human human(&age); //构造函数
Human human1(human); //调用合成的拷贝构造函数
Human human2(&age);
human = human2; //调用赋值构造函数
human.describe(); //改变前human的age值
human1.describe(); //改变前human1的age值
human2.describe(); //改变前human2的age值
human.changeAge();
std::cout << "改变后" << std::endl;
human.describe(); //改变后human的age值
human1.describe(); //改变后human1的age值
human2.describe(); //改变后human2的age值
system("pause");
return 0;
}
编程小白,如有错误,还请指正