cpp►引用变量,按值与按引用传递返回及销毁

Posted itzyjr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cpp►引用变量,按值与按引用传递返回及销毁相关的知识,希望对你有一定的参考价值。

■引用变量

int rats;
int& alias = rats; // 使alias成为rats的【别名】
#include <iostream>
int main() {
	using namespace std;
	int rats = 101;
	int& alias = rats;// alias是一个引用,它是rats的“别名”

	cout << "rats = " << rats;
	cout << ", alias = " << alias << endl;

	rodents++;
	cout << "rats = " << rats;
	cout << ", alias = " << alias << endl;

	rats++;
	cout << "rats = " << rats;
	cout << ", alias = " << alias << endl;

	cout << "rats address = " << &rats;
	cout << ", alias address = " << &alias << endl;
	return 0;
}
rats = 101, alias = 101
rats = 102, alias = 102
rats = 103, alias = 103
rats address = 00CFF6E4, alias address = 00CFF6E4

从输出结果可以看到,alias是rats的一个别名,所以它俩的地址总相同,它俩的值总是同步更新的。

引用更接近指针常量,必须在创建时进行初始化,一旦与某个变量关联起来,就将一直效忠于它(不易主)。——地址与地址上存的值总相同。

必须在声明引用时将其初始化,而不能像指针那样先声明再赋值:

int rat;
int& rodent;
rodent = rat; // 不允许
  1. 块作用域
void go() {
	Box box;
	// ...
}// 块结束,box对象被销毁
while(...) {
	int temp;
	// ...
}// 块结束,temp被回收
  1. 按值传递给函数参数
#include <iostream>
class Box {
private:
	int width;
	int height;
public:
	Box(int w, int h);
	int getW() { return width; }
	int getH() { return height; }
	void go(Box box);
};

Box::Box(int w, int h) : width(w), height(h) {};

void Box::go(Box box) {
	box.width = 1;
	box.height = 2;
	std::cout << "Inner:" << box.width << " , " << box.height << std::endl;
}

int main() {
	Box box(10, 20);
	box.go(box);
	std::cout << "Outer:" << box.getW() << " , " << box.getH();
}
Inner:1 , 2
Outer:10 , 20

从输出结果可以看到,按值传递进函数的实参其实是拷贝了一份副本给形参,所以更改形参数据完全不会影响原实参。
形参对象销毁过程:Box box; => Box copyBox(调用复制构造函数); => copyBox在函数块作用域完成相关操作 => copyBox销毁。

原始实参和函数形参在内存中是分开存储的,如下图:

  1. 按引用传递给函数参数
void Box::go(Box& box) {
	box.width = 1;
	box.height = 2;
	std::cout << "Inner:" << box.width << " , " << box.height << std::endl;
}

int main() {
	Box box(10, 20);
	box.go(box);
	std::cout << "Outer:" << box.getW() << " , " << box.getH();
}
Inner:1 , 2
Outer:1 , 2

从输出结果可以看到,传递进去的实参与形参是同一个对象,它们的地址是相同的。
由于形参是实参的一个别名,所以它是与实参生命周期相同,在main()块结束时自动一同销毁。

  1. 函数返回类型为值类型
Box go() {
	Box box(10, 20);
	return box;
}

对象box先拷贝一份copyBox(调用复制构造函数),成为返回对象,它与原box对象地址空间是不一样的。然后函数块作用域结束,box对象被析构销毁掉。

  1. 函数返回类型为引用类型
Box& go() {
	Box box(10, 20);
	return box;
}

返回的对象box的别名就是最终要返回的引用,返回值为引用型(Box&)的时候,返回的是地址。当函数返回引用类型时,没有复制返回值,返回的是对象本身。
那么,box对象在函数块结束时,会被销毁吗?当然会被销毁了,因为box对象就是典型的局部变量啊!所以,返回box对象地址后,box对象就被析构了,返回的引用对象就有问题了。所以用法是这样的:

Box& go(Box& b, ...) {
	// 操作b
	return b;
}

就是从外面传入一个对象引用,这个对象的生命周期就不在函数块作用域,所以传入的对象不会被销毁!就一切正常正确了。

以上是关于cpp►引用变量,按值与按引用传递返回及销毁的主要内容,如果未能解决你的问题,请参考以下文章

哪个更快?按引用传递与按值传递 C++

java的按值传递与按引用传递

Common Lisp:按值传递与按引用传递[重复]

在 C# 中将 REF 和 OUT 关键字与按引用传递和按值传递一起使用

Java:按值传递与按引用传递

在 C++ 中通过引用与按值将向量传递给函数