C++编程思想:指针,引用,拷贝构造函数,赋值运算符

本文深入探讨了C++中指针的引用与指针的指针的区别,解析了函数返回引用的工作原理,并详细阐述了拷贝构造函数及赋值运算符重载的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对指针的引用和指针的指针到底是怎么一回事?

#include<iostream>

int i = 47;
int* p = &i;
void f(int** ip)
{
	std::cout << "ip :" << ip <<std::endl;
	std::cout << "*ip :" << *ip <<std::endl;
	std::cout << "**ip :" << **ip <<std::endl;
}

void g(int* &dp)
{
	std::cout << "dp :" << dp << std::endl;
	std::cout << "*dp :" << *dp << std::endl;
	//std::cout << "**dp :" << **dp << std::endl; //error
}
// Error 
//void h(int&* p) {}
int main()
{
	std::cout << "&i的值:" << &i << std::endl;
	std::cout << "i的值:" << i << std::endl;
	std::cout << "&p的值" << &p << std::endl;
	std::cout << "p的值" << p << std::endl;
	std::cout << "*p的值" << *p << std::endl;
	f(&p);
	g(p);

	system("pause");

	return 0;
}

在这里插入图片描述
指针的引用:两个指针指向同一个变量,解引用的内容相同,不能进行解引用的解引用
指针的指针:第一个指针指向另一个指针地址(第一个指针中存了第二个指针的地址),第一次解引用活得一个指针中的内容(指向一个对象的地址),第二次解引用获得指针内容(地址)中的内容。

函数返回引用到底返回了什么?

函数返回引用,返回了一块不会随着函数结束而结束的内存,所以针对这个返回值,可以把它当作普通对象进行赋值,也可以对其进行引用。

int& f(int& x)
{
	std::cout << "&x : " << &x << endl;
	return x;
}


int main()
{
	int b = 1;
	std::cout << "&b " << &b<<endl;

	//int c = 1;
	//std::cout << "&c" << c;

	int& c = b;
	std::cout << "&c " << &c<<endl;

	int& d = f(b);

	int e = 1;
	std::cout << "&e " << &e << endl;

	e = f(b); //这里是一次赋值运算

	std::cout << "&f(b) " << &f(b) << endl;

	std::cout << "&d " << &d<<endl;

	std::cout << "&e " << &e << endl;

}

在这里插入图片描述
从程序运行的结果看,对于f()函数的返回值有两种使用方式,第一种只取其值,这样的话变量有自己的地址。第二种不仅取其值,还取其地址。

拷贝构造函数和默认拷贝构造函数

拷贝构造函数的调用出席在用一个类初始化另一个类的时候。默认拷贝构造函数再将类内的指针传递时采取按值传递的方式这样就会产生多个对象内的指针指向同一个地方。

自定义拷贝构造函数
#include <iostream>
#include <string>
using namespace std;

static int countA = 0;

class A
{
public:
	int* AI;

public:
	A() :AI(nullptr){
		AI = new int(countA);
		countA++;
		std::cout << "this is A() : " << countA << endl;
	}
	
	A(const A &a)
	{
		AI = new int(*a.AI);
		countA++;
		std::cout << "this is A(A&) : " << countA << endl;
	}
	
	
	~A() {
		countA--;
		std::cout << "this is ~A() : " << countA << endl;
		if (AI != nullptr);
		{
			std::cout << "*AI : " << *AI << endl;
			std::cout << "AI : " << AI << endl;
		}
	}
	
	A& operator = (const A& a)
	{
		AI = a.AI;
		std::cout << "this is operator = : " << countA << endl;
		return *this;
	}
	
};


void fA(A a) {};

int main()
{
	A a1;
	A a2 = A(a1);
	fA(a1);
}

在这里插入图片描述
指针的地址不一样

使用默认拷贝构造函数
#include <iostream>
#include <string>
using namespace std;

static int countA = 0;

class A
{
public:
	int* AI;

public:
	A() :AI(nullptr){
		AI = new int(countA);
		countA++;
		std::cout << "this is A() : " << countA << endl;
	}

	/*
	A(const A &a)
	{
		AI = new int(*a.AI);
		countA++;
		std::cout << "this is A(A&) : " << countA << endl;
	}
	*/
	
	
	~A() {
		countA--;
		std::cout << "this is ~A() : " << countA << endl;
		if (AI != nullptr);
		{
			std::cout << "*AI : " << *AI << endl;
			std::cout << "AI : " << AI << endl;
		}
	}
	
	A& operator = (const A& a)
	{
		AI = a.AI;
		std::cout << "this is operator = : " << countA << endl;
		return *this;
	}
	
};


void fA(A a) {};

int main()
{
	A a1;
	A a2 = A(a1);
	fA(a1);
}

在这里插入图片描述
指针地址一样。

=赋值运算符重载

#include <iostream>
#include <string>
using namespace std;

static int countA = 0;

class A
{
public:
	int* AI;

public:
	A() :AI(nullptr){
		AI = new int(countA);
		countA++;
		std::cout << "this is A() : " << countA << endl;
	}

	
	A(const A &a)
	{
		AI = new int(*a.AI);
		countA++;
		std::cout << "this is A(A&) : " << countA << endl;
	}
	
	
	
	~A() {
		countA--;
		std::cout << "this is ~A() : " << countA << endl;
		if (AI != nullptr);
		{
			std::cout << "*AI : " << *AI << endl;
			std::cout << "AI : " << AI << endl;
			delete AI;
		}
	}
	
	A& operator = (const A& a)
	{
		if (this == &a) //避免自赋值
		{
			return *this;
		}
		AI = new int (*a.AI);
		std::cout << "this is operator = : " << countA << endl;
		return *this;
	}
	
};


void fA(A a) {};

int main()
{
	A a1;
	A a2 = A(a1);
	fA(a1);
	A a3;
	a3 = a1;
}

当对象中有指针时,必须自定义拷贝构造函数 和 赋值运算符 否则在析构函数删除对象时会出错。为了防止出错可以删完在赋值为nullptr(这并不能保证不会出错).

#include <iostream>
#include <string>
using namespace std;

static int countA = 0;

class A
{
public:
	int* AI;

public:
	A() :AI(nullptr){
		AI = new int(countA);
		countA++;
		std::cout << "this is A() : " << countA << endl;
	}


	//没有拷贝构造函数会出错
	
	A(const A &a)
	{
		AI = new int(*a.AI);
		countA++;
		std::cout << "this is A(A&) : " << countA << endl;
	}
	
	
	
	
	~A() {
		countA--;
		std::cout << "this is ~A() : " << countA << endl;
		if (AI != nullptr);
		{
			std::cout << "*AI : " << *AI << endl;
			std::cout << "AI : " << AI << endl;
			delete AI;
			AI = nullptr;
		}
	}
	
	A& operator = (const A& a)
	{
		if (this == &a) //避免自赋值
		{
			return *this;
		}
		AI = new int (*a.AI); //这样不会产生错误
		//AI = a.AI; //这回产生错误
		std::cout << "this is operator = : " << countA << endl;
		return *this;
	}
	
};


void fA(A a) {};

int main()
{
	A a1;
	A a2 = A(a1);
	fA(a1);
	A a3;
	a3 = a1;
}

这个错误就是对于多个对象内的指针变量指向同一个地方,在析构函数中释放内存会产生的错误
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值