【Cpp巩固】引用与指针

2024-04-15 04:12
文章标签 指针 引用 cpp 巩固

本文主要是介绍【Cpp巩固】引用与指针,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【Cpp巩固】引用与指针

文章目录

  • 【Cpp巩固】引用与指针
    • 1.基本的语义差异
    • 2.使用场景
    • 3.可变性
    • 4.语法和便利性

笔者在学习Cpp的过程中老是会对指针和引用使用产生疑问,那本文就来详细对比一下指针和引用的区别。

1.基本的语义差异

  • 指针是一个变量,存储的是另一个变量的内存地址,指针可以被重复赋值指向相同类型的其他变量,也可以指向空指针nullptr
  • 引用是一个已经存在的变量的别名,并且引用必须在声明的时候就进行初始化,引用一旦定义就和该变量绑定了,作为该变量的别名,就不能指向别的变量。

举个例子:

#include <iostream>
using namespace std;int main() {int a = 10;int* a_ptr = &a;			// 声明一个指向a的指针int& a_ref = a;				// 声明一个指向a的引用cout << "This address of a is :" << &a << endl;cout << "This address of a_ptr is: " << &a_ptr << endl;cout << "This address of a_ref is: " << &a_ref << endl;cout << "a: " << a << " a_ptr: " << *a_ptr << " a_ref: " << a_ref << endl;*a_ptr += 10;				// 通过指针修改变量a的值cout << "a: " << a << " a_ptr: " << *a_ptr << " a_ref: " << a_ref << endl;a_ref += 10;				// 通过引用修改变量a的值cout << "a: " << a << " a_ptr: " << *a_ptr << " a_ref: " << a_ref << endl;return 0;
}

Output:

This address of a is :000000D68E3CF7C4
This address of a_ptr is: 000000D68E3CF7E8
This address of a_ref is: 000000D68E3CF7C4
a: 10 a_ptr: 10 a_ref: 10
a: 20 a_ptr: 20 a_ref: 20
a: 30 a_ptr: 30 a_ref: 30

这个例子中创建了一个变量a,然后创建了指向a的指针a_ptr,同时创建了指向a的引用a_ref,通过指针a_ptr和引用a_ref我们都能访问并且修改变量a的值,a_ref与变量a的地址完全一样,可以视作a_ref就是变量a的另一个别名。

2.使用场景

  • 指针可以在需要直接操作内存地址或者需要能够指向NULL的常见下使用,例如动态内存管理、数据结构的实现等。
  • 引用通常用于函数的参数传递过程中,尤其是传递大对象的时候避免了复制成本,或者当你需要确保传递的参数总是指向一个有效的对象时。

我们可以使用指针来进行动态内存管理,举个例子:

#include <iostream>int main() {int size;std::cout << "Please Enter the Size of Elements: ";std::cin >> size;int* array = new int[size];			// 动态分配内存for (int i = 0; i < size; i++) {	// 初始化数组array[i] = (i + 1);}std::cout << "Array Elements: " << std::endl;for (int i = 0; i < size; i++) {std::cout << array[i] << " ";}delete[] array;return 0;
}

Output:

Please Enter the Size of Elements: 10
Array Elements:
1 2 3 4 5 6 7 8 9 10

在这个例子中,指针 array 被用来指向一个动态分配的整数数组。通过使用 newdelete[],我们可以控制内存的分配和释放,这是引用无法完成的任务。

我们可以使用引用来进行大型的参数传递,举个例子:

#include <iostream>
#include <vector>void proccessVector(const std::vector<int>& vec) {std::cout << "Vector Elements: " << std::endl;for (int elem : vec) {std::cout << elem << " ";}return;
}int main() {std::vector<int> vec = { 1, 2, 3, 4, 5, 7, 8, 9, 10 };// 使用引用进行参数传递,避免参数复制proccessVector(vec);return 0;
}

在这个例子中,std::vector<int> 是一个可能包含大量数据的对象。通过使用引用,我们传递了一个到 processVector 函数的引用,避免了数据的复制。此外,使用 const 关键字确保函数内部不会修改向量的内容。

3.可变性

  • 指针可以指向常量const int* prt,或者指针本身可以是常量int* const prt,或者两者都是const int* const ptr
  • 引用通常不称其为"常量引用",但是可以有指向常量的引用cosnt int& ref,这意味着不能通过修改其所指向的变量的值
#include <iostream>int main() {int x = 10;int y = 20;// 指针指向非常量数据int* ptr = &x;*ptr = 15;std::cout << "New value of x: " << x << std::endl;// 指针指向常量数据const int* ptrToConst = &y;// *ptrToConst = 25;	// 错误,不能通过指向常量的指针修改数据// 常量指针int* const constPtr = &x;*constPtr = 25;// constPtr = &y;		// 错误,不能修改常量指针的指向// 常量指针指向常量数据const int* const constPtrToConst = &y;// *constPtrToConst = 30; // 错误:不能修改y的值// constPtrToConst = &x; // 错误:常量指针不能改变指向return 0;
}

4.语法和便利性

  • 指针的操作需要使用*(解引用)和->(成员访问)
  • 引用的使用就像使用普通变量一样,不需要使用特殊的符号来进行访问

我们编写一个汽车类,然后使用指针和引用两种方式来操作这个汽车类的实例,举个例子:

#include <iostream>
class Car {public:void start() {std::cout << "Car started!" << std::endl;}
};int main() {Car mycar;Car* carPtr = &mycar;Car& carRef = mycar;// 使用指针访问成员函数carPtr->start();// 使用引用访问成员函数carRef.start();return 0;
}

Output:

Car started!
Car started!

这篇关于【Cpp巩固】引用与指针的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/904820

相关文章

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

C语言指针入门 《C语言非常道》

C语言指针入门 《C语言非常道》 作为一个程序员,我接触 C 语言有十年了。有的朋友让我推荐 C 语言的参考书,我不敢乱推荐,尤其是国内作者写的书,往往七拼八凑,漏洞百出。 但是,李忠老师的《C语言非常道》值得一读。对了,李老师有个官网,网址是: 李忠老师官网 最棒的是,有配套的教学视频,可以试看。 试看点这里 接下来言归正传,讲解指针。以下内容很多都参考了李忠老师的《C语言非

JavaSE(十三)——函数式编程(Lambda表达式、方法引用、Stream流)

函数式编程 函数式编程 是 Java 8 引入的一个重要特性,它允许开发者以函数作为一等公民(first-class citizens)的方式编程,即函数可以作为参数传递给其他函数,也可以作为返回值。 这极大地提高了代码的可读性、可维护性和复用性。函数式编程的核心概念包括高阶函数、Lambda 表达式、函数式接口、流(Streams)和 Optional 类等。 函数式编程的核心是Lambda

C和指针:字符串

字符串、字符和字节 字符串基础 字符串就是一串零个或多个字符,并且以一个位模式为全0的NUL字节结尾。 字符串长度就是字符串中字符数。 size_t strlen( char const *string ); string为指针常量(const修饰string),指向的string是常量不能修改。size_t是无符号数,定义在stddef.h。 #include <stddef.h>

【C++】作用域指针、智能指针、共享指针、弱指针

十、智能指针、共享指针 从上篇文章 【C++】如何用C++创建对象,理解作用域、堆栈、内存分配-CSDN博客 中我们知道,你的对象是创建在栈上还是在堆上,最大的区别就是对象的作用域不一样。所以在C++中,一旦程序进入另外一个作用域,那其他作用域的对象就自动销毁了。这种机制有好有坏。我们可以利用这个机制,比如可以自动化我们的代码,像智能指针、作用域锁(scoped_lock)等都是利用了这种机制。

MFC中App,Doc,MainFrame,View各指针的互相获取

纸上得来终觉浅,为了熟悉获取方法,我建了个SDI。 首先说明这四个类的执行顺序是App->Doc->Main->View 另外添加CDialog类获得各个指针的方法。 多文档的获取有点小区别,有时间也总结一下。 //  App void CSDIApp::OnApp() {      //  App      //  Doc     CDocument *pD

C和指针:结构体(struct)和联合(union)

结构体和联合 结构体 结构体包含一些数据成员,每个成员可能具有不同的类型。 数组的元素长度相同,可以通过下标访问(转换为指针)。但是结构体的成员可能长度不同,所以不能用下标来访问它们。成员有自己的名字,可以通过名字访问成员。 结构声明 在声明结构时,必须列出它包含的所有成员。 struct tag {member-list} variable-list ; 定义一个结构体变量x(包含

17 通过ref代替DOM用来获取元素和组件的引用

重点 ref :官网给出的解释是: ref: 用于注册对元素或子组件的引用。引用将在父组件的$refs 对象下注册。如果在普通DOM元素上使用,则引用将是该元素;如果在子组件上使用,则引用将是组件实例: <!-- vm.$refs.p will be the DOM node --><p ref="p">hello</p><!-- vm.$refs.child will be the c

hot100刷题第1-9题,三个专题哈希,双指针,滑动窗口

求满足条件的子数组,一般是前缀和、滑动窗口,经常结合哈希表; 区间操作元素,一般是前缀和、差分数组 数组有序,更大概率会用到二分搜索 目前已经掌握一些基本套路,重零刷起leetcode hot 100, 套路题按套路来,非套路题适当参考gpt解法。 一、梦开始的地方, 两数之和 class Solution:#注意要返回的是数组下标def twoSum(self, nums: Lis

类模板中.h和.cpp的实现方法

一般类的声明和实现放在两个文件中,然后在使用该类的主程序代码中,包含相应的头文件".h"就可以了,但是,模板类必须包含该其实现的.cpp文件才行。也就是说,在你的主程序中,将 #include"DouCirLList.h" 替换成 #include"DouCirLList.cpp" 应该就可以了。 在使用类模板技术时,可在.h中实现,也可在.h和.cpp中分开实现,若用.h实