前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++入门知识(二)

C++入门知识(二)

作者头像
海盗船长
发布2020-08-27 17:18:53
4980
发布2020-08-27 17:18:53
举报
文章被收录于专栏:基础知识文章基础知识文章

6.引用

1.什么是引用?

代码语言:javascript
复制
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
**类型& 引用变量名(对象名) = 引用实体;**
代码语言:javascript
复制
void TestRef()
{
	int a = 10;
	int& ra = a;//<====定义引用类型
	printf("%p\n", &a);
	printf("%p\n", &ra);
	cout << a << endl;
	cout << ra << endl;
	ra -= 1;
	cout << a << endl;
	cout << ra << endl;
}
int main()
{
	TestRef();
	system("pause");
	return 0;
}

执行结果:

2.引用特性:

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体
代码语言:javascript
复制
void TestRef2()
{
	int a = 10;
	//int& ra;   // 该条语句编译时会出错,定义时没有初始化
	int& ra = a;
	int& rra = a;
	printf("%p %p %p\n", &a, &ra, &rra);
}

3.常引用

常引用声明方式:const 类型标识符&引用名=目标变量名;

代码语言:javascript
复制
void TestConstRef()
{
const int a = 10;
//int& ra = a;   // 该语句编译时会出错,a为常量
const int& ra = a;
// int& b = 10; // 该语句编译时会出错,b为常量
const int& b = 10;
double d = 12.34;
//int& rd = d; // 该语句编译时会出错,类型不同
const int& rd = d; }

用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。

4.引用场景

1、传递可变参数 2.做返回值

代码语言:javascript
复制
void Swap(int& left, int& right) {
	int temp = left;
	left = right;
	right = temp;
}
int& TestRefReturn(int& a) {
	a += 10;
	return a;
}
int main()
{
	int a = 8, b = 9; Swap(a, b);
	cout << a << b << endl;
	TestRefReturn(a);
	cout << a << endl;
	return 0;
}
在这里插入图片描述
在这里插入图片描述

注意:如果函数返回时,离开函数作用域后,其栈上空间已经还给系统,因此不能用栈上的空间作为引用类型 返回。如果以引用类型返回,返回值的生命周期必须不受函数的限制(即比函数生命周期长)。

5.引用和指针的区别

★ 相同点: 都是地址的概念; 指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名。 ★ 区别: 1. 指针是一个实体,而引用仅是个别名; 2. 引用使用时无需解引用(*),指针需要解引用; 3. 引用只能在定义时被初始化一次,之后不可变;指针可变; 4. 引用没有 const,指针有 const; 5. 引用不能为空,指针可以为空; 6. “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小; 7. 指针和引用的自增(++)运算意义不一样; 8.从内存分配上看:程序为指针变量分配内存区域,而引用不需要分配内存区域。

7内联函数

1什么是内联函数?

内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。但在选择使用内联函数时,必须在程序占用空间和程序执行效率之间进行权衡,因为过多的比较复杂的函数进行内联扩展将带来很大的存储资源开支。另外还需要特别注意的是对递归函数的内联扩展可能引起部分编译器的无穷编译。

2内联函数的特性

  1. 内联函数是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜使用作为内联函数。
  2. 内联函数对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联。
  3. 内联函数不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。
代码语言:javascript
复制
// F.h
#include <iostream>
using namespace std;
inline void f(int i);
// F.cpp
#include "F.h"
void f(int i) {
cout << i << endl; }
// main.cpp
#include "F.h"
比特科技
int main()
{ f(10);
return 0; }
// 链接错误:main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl f(int)" (?
f@@YAXH@Z),该符号在函数 _main 中被引用

8auto关键字

auto是一个C/C++语言存储类型,仅在语句块内部使用,初始化可为任何表达式,其特点是当执行流程进入该语句块的时候初始化可为任何表达式。

代码语言:javascript
复制
#include<iostream>
using namespace std;
int TestAuto()
{
	return 10;
}
int main()
{
	int a = 10;
	auto b = a;
	auto c = 'a';
	auto d = TestAuto();
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;
	//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
	system("pause");
	return 0;
}

运行结果:

在这里插入图片描述
在这里插入图片描述

【注意】使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。

auto如何使用?

1. auto与指针和引用结合起来使用 用auto声明指针类型时,用auto和auto*没有区别,但用auto声明引用类型时则必须加& 2. 在同一行定义多个变量 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

代码语言:javascript
复制
#include<iostream>
using namespace std;
void TestAuto()
{
	auto a = 1, b = 2;
	//auto c = 3, d = 4.0;  // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}
int main()
{
	int a = 10;
	auto b = a;
	auto c = 'a';
	auto* e = &a;
	auto& f = a;
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(e).name() << endl;
	cout << typeid(f).name() << endl;
	system("pause");
	return 0;
}
在这里插入图片描述
在这里插入图片描述

以下情况auto不能使用

  1. auto不能作为函数的参数 // 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导void TestAuto(auto a) {}
  2. auto不能直接用来声明数组
代码语言:javascript
复制
void TestAuto()
{
    int a[] = {1,2,3};
    auto b[] = {4,5,6};
}

9基于范围的for循环

用法:

for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。 语法形式:

代码语言:javascript
复制
for(declaration:expression)
{
	statement
}

其中: expression部分表示一个对象,用于表示一个序列。 declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。 每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值。

基于范围的for循环特点

(1)和普通循环一样,也可以采用continue跳出循环的本次迭代。 (2)用break来终止整个循环

代码语言:javascript
复制
#include <iostream>
#include <vector>
using namespace std;

int main()
{
	int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	for (int y : x) { 
		cout << y << " ";
	}

	for (auto y : x) {
		cout << y << " ";
	}
	cout << endl;

	for (auto &y : x) { 
		cout << y << " ";
	}
	cout << endl;

	for (const auto &y : x) { 
		cout << y << " ";
	}
	cout << endl;
	cout << "end of integer array test" << endl;
	cout << endl;

	vector<double> v;
	for (int i = 0; i < 10; ++i) {
		v.push_back(i + 0.14159);
	}

	for (const auto &j : v) {
		cout << j << " ";
	}
	cout << endl;
	cout << "end of vector test" << endl;
	system("pause");
}
在这里插入图片描述
在这里插入图片描述

10指针空值nullptr

nullptr:是C++空指针类型的关键字,nullptr是在C++11中引入的。 传统意义上来说,c++把NULL、0视为同一种东西,有些编译器将NULL定义为 ((void*)0),有些将其定义为0.

c++不允许直接将void隐式的转化为其他类型,但是如果NULL被定义为 ((void)0), 当编译char p = NULL;NULL只好被定义为0。 还有: void func(int); void func(char); 如果NULL被定义为0,func(NULL)会去调用void func(int),这是不合理的 所以引入nullptr,专门用来区分0、NULL。 nullptr的类型为nullptr_t,能够隐式的转换为任何指针。

nullptr 与 nullptr_t:

代码语言:javascript
复制
typedef decltype(nullptr) nullptr_t; 

注意:

  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

总结,刚接触C++,整理的知识不是很有条理,有问题的地饭否还望指出!!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 6.引用
    • 1.什么是引用?
      • 2.引用特性:
        • 3.常引用
          • 4.引用场景
            • 5.引用和指针的区别
            • 7内联函数
              • 1什么是内联函数?
                • 2内联函数的特性
                  • auto如何使用?
                  • 以下情况auto不能使用
                  • 用法:
                  • 基于范围的for循环特点
              • 8auto关键字
              • 9基于范围的for循环
              • 10指针空值nullptr
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档