首页 > 编程语言 >c++初阶入门(持续更新)

c++初阶入门(持续更新)

时间:2023-04-18 16:33:36浏览次数:37  
标签:初阶 变量 int auto 函数 定义 c++ 引用 入门

1.命名空间

目的:解决c语言的缺陷,命名冲突。

#include<stdio.h>

int rand=0;
int main()
{
    
  printf("%d",rand);
}

上面这段程序是可以运行的

但是!

#include<stdio.h>
#include<stdlib.h>
int rand=0;

int main()
{
  printf("%d",rand);
}

那么上面的代码就会报错。因为stdlib.h 那么包含了rand这个函数 ,我们重新定义rand 那么出现报错。命名被重复定义了。

1.1命名空间定义一个域

关键字 namespace +空间名

namespace std
// namespace name
{
    string a="zhangsan";
}

1.2访问全局域和命名空间作用域

//全局域
int a=0;
//命名空间
namespace bit
{
  int a=1;

}
//局部域
int main()
{
  int a=2;
  
  printf("%d\n",::a);   //访问的全局域 
   printf("%d\n",a);  //访问局部域2
  printf("%d\n",bit::a); //访问命名空间
}

变量搜索顺序:局部域→全局域→展开命名空间or指定访问命名空间域。

展开命名空间 ------→相当于把变量暴露到了全局 ,编译时是否去命名空间搜索

using namespace std; //可以直接使用命名空间的变量不重复

1.3 定义命名空间

命名空间内可以定义函数、变量、结构体、和再嵌套命名空间。

namespace bit
{
 // 命名空间中可以定义变量/函数/类型
 int a = 0;
 int b = 1;
 int Add(int left, int right)
 {
    return left + right;
 }
 struct Node
 {
    struct Node* next;
    int val;
 };
}
int main()
{
    // 编译报错:error C2065: “a”: 未声明的标识符
    printf("%d\n", a);
    return 0;
}

1.4 命名空间的合并

当我们在多个头文件里面定义了同名的命名空间,当我们调用这些头文件的时候会进行合并两个定义的变量,结构体、函数、嵌套的命名空间,切记不要重复定义变量和函数,可以选择再嵌套一个命名空间来包含这个变量。

1.5 注意事项

using namespace std;

直接展开会有风险,我们定义如果和库重名,就报错了。

建议项目不要直接展开,还是推荐直接指定来访问。

那么问题来了,项目里面我都去指定?

解决办法:把常用展开,只是展开部分

using std::cout;
using std::endl;

2.C++输入&输出

<< 叫流插入运算符

叫流提取运算符

cout<<"hello heshiqiang"<<endl;

cin>>x;

关键字 :cout cin

特性:自动识别类型 ,可以不用定义类型

作用:输入输出

注意:cin自动识别精度到小数点后一位。 当我们要输入和输出小数点后2位,那么还是乖乖用printf和scanf来控制输入输出。

3.函数重载

c中还是不能进行函数重载。同一作用域下c++中可以重复定义多个同名的函数,但是有一定的要求,如下:

  • 函数名相同,参数类型顺序不同
  • 函数名相同,参数个数不同
#include<iostream>
using namespace std;
//第一个add
int add(int a, int b)
{
	return a + b;


}
//第二个add
void add(double a, double b)
{
	printf("%lf\n", a + b);
}
int main()
{
	//函数重载
	int ret = add(10, 20);
	printf("%d\n", ret);
	add(10.0, 20.0);
    //这里体现的是函数名相同,参数类型顺序不同
    //同理 我们可以改变参数个数 一样可以调用同名函数


	return 0;
}

注意: 改变函数的返回值是无法进行函数重载,必须是上面规定的两条。

那么调用速度会不会变慢?

编译之后,代码变成指令,通过指令找到函数的地址,速度还是很快的,那么如何找到呢,我们打开反汇编指令查看可以发现,c++对函数名进行了修饰,,call找到修饰之后的地址,实现这个函数重载功能。

c++调用函数时候add之后进行了修饰,call指令通过修饰后的地址找到这个函数

那么如何修饰的呢?

第一个add: XXaddii(ii,就是int int)

第二个add:XXadddd(dd,就是double double)

这也是为什么顺序不同,找到的函数会不一样

4.引用

4.1 引用概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。

比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。

相当于给人取别名

&

1.取地址

例如:scanf("%d",&a);

2.引用

例如:int& k=i;
  • &放到变量前面,那么就是取地址
  • &放到数据类型的后面,那么就是引用

下面就是演示代码

int main()
{
	int a = 10;
	int& k = a;
	int b = a;

	cout << &a << endl;
	cout << &k << endl;
	cout << &b << endl;
	return 0;
}
//实现结果

c++初阶入门(持续更新)_学习笔记

可以看到就是a就是k,k就是i。那么a++了,k也就++了,不影响b。

4.1.1引用特性总结


  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体

4.2 多层引用问题

//重新给a取一个别名 这个是合理的
//我们允许一个变量有多个别名
int& m=a;
//这个也是被允许的 m是a的别名 那么给m再起一个别名
int& j=m;  // x

那么我们可以推广到指针的别名,结构体的别名,函数的别名

4.3使用场景

4.3.1做参数(输出型参数)

1.形参的改变要改变实参

2.提高效率(大对象/深拷贝)

void Swap(int& a,int& b)
{
  int temp=a;
  a=b;
  b=temp;
}
#include <time.h>
#include<iostream>
using namespace std;
struct A { int a[10000]; };

void TestFunc1(A a) {}

void TestFunc2(A& a) {}

void TestRefAndValue()
{
	A a;
	// 以值作为函数参数
	size_t begin1 = clock();
	for (size_t i = 0; i < 10000; ++i)
		TestFunc1(a);
	size_t end1 = clock();
	// 以引用作为函数参数
	size_t begin2 = clock();
	for (size_t i = 0; i < 10000; ++i)
		TestFunc2(a);
	size_t end2 = clock();
	// 分别计算两个函数运行结束后的时间
	cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
	cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}

int main()
{
	TestRefAndValue();

	return 0;
}

运行截图:

c++初阶入门(持续更新)_auto_02

4.3.2做返回值
  • 常用的传值返回(没有用&)
int add(int a,int b)
{
  return a+b;//返回的时候如果是小量数据那么就会被放到寄存器里面 开一个临时变量
  //来存储这个临时拷贝
}
  • 引用返回

注意事项:就是函数的放回,出了作用域,如果返回的对象没有还给系统,那么才能使用引用传值。(如何保持出了定义的函数作用域还不还给系统,那么我们一般定义全局变量)

#include<iostream>
using namespace std;
int c=0;
int& add(int a,int b)
{
  int c=a+b;
  return c;
}
int main()
{
  int a=add(10,10);
}
  • 在返回大对象的时候,引用返回和常用的传值返回比较
#include <time.h>
#include<iostream>
using namespace std;
struct A{ int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a;}
// 引用返回
A& TestFunc2(){ return a;}
void TestReturnByRefOrValue()
{
 // 以值作为函数的返回值类型
 size_t begin1 = clock();
 for (size_t i = 0; i < 100000; ++i)
 TestFunc1();
 size_t end1 = clock();
 // 以引用作为函数的返回值类型
 size_t begin2 = clock();
 for (size_t i = 0; i < 100000; ++i)
 TestFunc2();
 size_t end2 = clock();
 // 计算两个函数运算完成之后的时间
 cout << "TestFunc1 time:" << end1 - begin1 << endl;
 cout << "TestFunc2 time:" << end2 - begin2 << endl;
}


int main()
{
  TestReturnByRefOrValue();
}

运行结果:

c++初阶入门(持续更新)_c++_03

通过测试,传值和用引用在效率方面有很大的区别。引用效率更高。

引用返回值的时候权限的改变

int func1()
{
	static int x = 0;
	return x;
}
int& func2()
{
	static int x = 0;
	return x;
}

int main()
{
	//const int& ret1 = func1();  //权限平移
	//int& ret1 = func1(); //权限放大
	//int ret1 = func1(); //拷贝

	//int& ret2 = func2(); //权限平移
	//const int& ret2 = func2();  //权限缩小 被const修饰具有常性不可修改
    
  
    //出现整型提升 整型转换 就一定会生成一个临时变量来先整型提升或者转换再赋值
    
    double dd=1.11;
    int ii=dd;
    const int & rii=dd;
    //在发生整型提升或者整型转换 都会生成一个临时变量,然后就是把临时变量放到rii里面
//	//然后 临时变量具有常性   const修饰之后也有常性

	return 0;
}

4.4 引用和指针之间的区别

  1. 引用是和原来的实体共用一个空间,相当于还是同一个人,只是不同的名称,不需要开辟空间。
  2. 引用是按照指针的方式实现的。
int main()
{
    int a = 10;
  
  //语法层面:不开空间,是对a取别名
    int& ra = a;
    ra = 20;
  //语法层面:开空间,存储a的地址
    int* pa = &a;
    *pa = 20;
    return 0;
}

上面一段代码的汇编代码对比

c++初阶入门(持续更新)_学习笔记_04

我们可以通过观察发现,底层实现原理是一致的。

引用和指针的不同点:

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
  2. 引用在定义时必须初始化,指针没有要求
  3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  4. 没有NULL引用,但有NULL指针
  5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
  6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  8. 引用比指针使用起来相对更安全

10.权限不能放大,例如 const int a=0; int& b=a; 这个地方就是错误的

引用总结: 1.、基本任何场景都可以用引用传参。

2、谨慎使用

5.auto关键字特性和使用

我个人认为auto挺好用的,不用自己推断数据类型,编译器自动帮我推断,当写工程的时候,可以避免因为单词拼写错误出现的报错。

5.1定义

auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

5.2auto的特性

1.可以推导初始化的数据类型

2.要想使用auto必须进行初始化

3.可以同行声明多个变量,但是变量数据类型要一致

5.3auto的使用

#include<iostream>
using namespace std;
int main()
{
    auto a=10;   //初始化 并能推断出a的类型为int
    auto b=10,c=11; //同行定义多个变量 多个变量数据类型是一致的
  
    cout<<a<<" "<<b<<" "<<c<<" "<<endl;
  
    return 0;
}
int main()
{
	//int a = 0;
	//int b = a;
	//auto c = a;   //根据右边表达式的类型推导c的类型

	//auto d = c + 1.11;     
	//cout << typeid(c).name() << endl;
	//cout << typeid(d).name() << endl;

	vector<int> v;
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//简化使用迭代器
	auto a = v.begin();
	//遍历数组读出数组内容
	for (auto i : arr)
	{
		cout << i << " " << endl;
	}

	//修改数组里面的内容
	for (auto& i : arr)
	{
		i *= 2;
	}
	return 0;
}

标签:初阶,变量,int,auto,函数,定义,c++,引用,入门
From: https://blog.51cto.com/u_15831056/6203659

相关文章

  • 【内附源码和文档】基于C++14异步蒙特卡洛工具函数
    Simple-Monte-Carlo-Tool-Function这是一个使用C++实现的简单的异步蒙特卡洛算法工具函数C++标准:C++14使用autores=MonteCarlo(sample_nums,check_sample_funtion,generate_sample_funtion,…args);doublep=res.get();std::cout<<p<<std::endl;sample_nums:需要生成的样......
  • linux蚁剑入门到熟悉文档地址整理
    linux蚁剑入门到熟悉文档地址收录蚁剑GetHub地址帮助文档kali安装出现问题的解决方式kali安装记录linuxdebian下载解压后进入文件内,使用root身份执行./AntSword后选择下载运行环境,新建并选择位置即可之后再次./AntSword即可......
  • 阿里6年测试经验,4个步骤教你入门自动化测试(建议收藏)
    ​ 前言随着软件测试技术的发展,人们已经从最初的纯粹的手工测试转变为手工与自动化测试技术相结合的测试方法。近年来,自动化测试越来越受到人们的重视,对于自动化测试的研究也越来越多。背景项目版本功能日趋增加,系统模块越来越多,功能趋于完善,此外系统经常更新,测试人员无法满......
  • C++基础1: 命名空间
    0.前言C++是在C语言基础之上的一门语言,所以学习C++的第一步是思考C++是如何优化C语言设计中的一些不足,如作用域,IO,函数,指针,宏等这些内容同时也是为之后学习C++类和对象打基础,下面说一下C++是如何优化C语言中的作用域1.命名空间在说明命名空间的概念和如何优化......
  • docker入门之三:docker构建私有镜像入门到实践
    1.docker构建私有镜像1.1.使用Dockerfile定制镜像1.2.构建镜像1.docker构建私有镜像1.1.使用Dockerfile定制镜像在空目录创建文件,命名为Dockerfile[hadoop@hadoop101file]$cddocker/[hadoop@hadoop101docker]$mkdirmydockerfile[hadoop@hadoop101dock......
  • docker入门之二:docker常用命令
    1.docker常用命令1.1.基本命令1.2.docker管理容器1.2.1.启动容器进入容器删除容器1.docker常用命令1.1.基本命令获取镜像[hadoop@hadoop101docker]$dockerpullubuntu:16.04运行镜像[hadoop@hadoop101docker]$dockerrun-it--rmubuntu:16.0......
  • docker入门之一:docker基础概念与安装
    1.Docker简单介绍1.1.什么是docker?1.2.Docker和传统虚拟机1.3.为什么使用docker1.4.docker架构2.Docker安装2.1.docker版本命名2.2.docker安装2.3.docker卸载2.4.docker镜像加速器1.Docker简单介绍1.1.什么是docker?googlego语言开发,基于Linux内......
  • 动力节点2023最新MybatisPlus学习笔记(一)入门篇
    MyBatis是很火的框架,一般的项目都是基于ssm,虽然mybatis可以直接在xml中通过SQL语句操作数据库,很灵活,但其操作都要通过SQL语句进行,就必须写大量的xml文件,非常麻烦。而MyBatis-Plus可以很好的解决了这个问题,比Mybatis简单太多了,不用搞那么多xml文件的配置,直接与Springboot整合,开发效......
  • performance_schema 笔记(一)—— 简介与快速入门
    系列文章参考自《MySQL性能优化金字塔法则》,删除了书里重复说明和过于复杂的一些解释,完整版请参考原书。第一篇将简单介绍performance_schema是什么、有什么用、用法快速入门,它由哪些表组成以及这些表的用途。 一、performance_schema简介performanceschema是运行在较低级别的......
  • C++重载的奥义之运算符重载
    0、引言        重载,顾名思义从字面上理解就是重复装载,打一个不恰当的比方,你可以用一个篮子装蔬菜,也可以装水果或者其它,使用的是同一个篮子,但是可以用篮子重复装载的东西不一样。        正如在之前的文章《重载的奥义之函数重载》中介绍的类似,函数的重载是指利......