C++之引用类型,深浅拷贝构造

引用类型:给内存段取别名。

int m = 10;
//引用,给内存段取别名,所以需要给他一段内存段,而不只是声明。
int& n = m;//不是赋值的意思,是别名的意思

想要在被调函数中修改主调函数中定义的变量的值时,不需要将其地址传输给被调函数,直接传输变量即可,但需要注意的是,被调函数的形参类型必须为引用类型,否则就无法达到修改主调函数中变量的值的目的。

需不需要在被调函数中修改主调函数中变量的值?
如果需要修改则才需要将将被调函数的形参改为引用类型,如果不需要修改则不需要将被调函数的形参改为引用类型。

使用方法:

#include <stdio.h>

void modify(int& a,int& b) // 形参为引用类型  双向
{
	int p;
    p = a;
    a = b;
    b = p;
	// 此时的a,b就是就是main中的a,b
}

int main()
{
	int a = 10;  // 在main函数中定义的整型变量a
    int b = 20;  // 在main函数中定义的整型变量a

	swap(a,b);
	// 在C++程序中,只需要传输变量名即可在swap中修改值
	// 但前提是,modify函数的形参必须是引用类型
	printf("%d %d\n", a,b);

	return 0;
}

引用类型和指针的区别?

1.基本概念
指针:指的是一块内存的地址值。
引用:是一块内存的别名。

指针本质上就是存放变量地址的一个变量,逻辑上是独立的。他可以被改变,包括其指向的地址的改变和其指向的地址中所存放的数据的改变。

而引用只是一个别名,逻辑上并不存在,在整个引用周期是不能被改变的,只能指向同一个变量。

2.能否为空值
指针是可以为空值的,可以不需要初始化。平时编程中,最讨厌的情况就是看到各种NullPointer,排查起来都不好排查。
引用不能为空值,因此必须进行初始化。所以引用的一个优点是它一定不为空,相对于指针不用检查它所指对象是否为空,这样增加了效率。

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

void swap(int a, int b) {
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
}

void swap2(int* a, int* b) {
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
}

void swap3(int &a, int &b) {
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
}

int main(int argc, char const *argv[])
{
    int i = 1, j = 2;
    //swap(i, j);
    //swap2(&i, &j);
    swap3(i, j);
    printf("i=%d, j=%d", i, j);
    return 0;
}

 上面有三种传递参数的方式:直接传递变量名,传递变量地址,以及传递引用。

如果我们执行swap(i, j)方法,显然在函数调用结束以后,main方法里面的i,j值并没有发生变化。

执行swap2(&i, &j)方法,形参是指针变量,实参是一个变量的地址,调用函数时,形参得到的实参变量的地址,因此指向实参的变量单元,可以实现在main方法里交换i,j值的目的。但是该方法不够直观,而且依旧是“值传递”的方式,只不过传递的是变量的地址而已。

当执行swap3(i, j)方法时,形参是声明的引用,调用函数的过程中,实现了引用的初始化,这是传入的实参就是变量,而不是数值,所以做到了真正意义上的“变量传递”,最后在main方法里面也交换了i, j的数值。

 数组用引用也很方便,得到内存段的地址,可以直接求数组长度,不断再参数里传长度了。

拷贝构造:

class A{
    int n;
public:
    A();
    A(int n){
        this->n = n;
    }
    ~A();
};

A a,b(10);

A c = a;            //拷贝构造
A d(c);             //拷贝构造

浅拷贝:

直接存储资源(指针直接指向背拷贝对象的内存段)

深拷贝:

重新分配资源,保存数据的备份

// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Copy_Construction.h"

int _tmain(int argc, _TCHAR* argv[])
{
	Copy_Construction a("111");
	printf("p:%p\n","111");
	a.Show();

	Copy_Construction b(a);
	a.Show();
	b.Show();

	while (true)
	{

	}
	return 0;
}

#pragma once
#include <string.h>
class Copy_Construction
{
	char* pname;
	int size;
public:
	Copy_Construction();
	Copy_Construction(char* name);
	Copy_Construction(Copy_Construction &member);
	void Show();
	~Copy_Construction();
};

#include "stdafx.h"
#include "Copy_Construction.h"


Copy_Construction::Copy_Construction()
{
	this->pname = NULL;
	this->size = 0;
}

Copy_Construction::Copy_Construction(char* name)
{
	//深拷贝:
	this->size = strlen(name);				//求出传入的字符串的长度
	this->pname = new char[size +1];		//申请一块内存空间,保存输入备份
	memset(this->pname,0,size+1);			//空间清零
	strcpy(this->pname,name);				//赋值

	//浅拷贝:
	//this->pname = name;					//直接指向传入的参数的内存段位置
	//this->size = strlen(name);			//传入的参数的长度
}

Copy_Construction::Copy_Construction(Copy_Construction &member)
{
	this->size = strlen(member.pname);				//求出传入的字符串的长度
	this->pname = new char[size + 1];				//申请一块内存空间,保存输入备份
	memset(this->pname, 0, size + 1);				//空间清零
	strcpy(this->pname, member.pname);				//赋值
}
Copy_Construction::~Copy_Construction()
{
	delete[] pname;
}

void Copy_Construction::Show()
{
	printf("p:%p\n", this->pname);
}

猜你喜欢

转载自blog.csdn.net/makabaka12138/article/details/128513314