C++——基础(指针、字符串、输入输出、结构体、引用、函数、模板)

本文档详细介绍了C++的基础知识,包括main函数、常量、关键字、字符串操作、输入输出、命名空间等内容。此外还深入讲解了结构体、共用体、指针等高级主题,并对比了引用与指针的区别。

1. 基础

1.1

  1. C++区分大小写,拓展名为cpp
  2. C++头文件扩展名没有扩展名,有些C的头文件转化为C++头文件,去掉h头文加上前缀c(math.h->cmath)

main函数

  • C++的标准主函数形式

    int main()
    {
    
    }
    
  • C语言标准主函数

    int main(void)
    {
    
    }
    
  • c++标准

    # include <iostream>
    using namespace std;
    

2.常量

作用:记录不可更改的数据

  1. #define 宏定义:
    #define 常量名 常量值
    #define week 7
    
  2. const 修饰的变量
  • const作用是保护被定义的值不被改变。
    const 数据类型 常量名=常量值
    const int week=7; // 是week的值一直为7
    week=2;  //就会报错
    

3.关键字

sizeof关键子

  • 作用:统计数据类型所占内存大小
  • 语法:sizeof(数据类型或者变量名)
cout << "long型所占内存大小:"<< sizeof(long) << endl;

endl

  • 作用:换行
  • endl:屏幕光标移到下一行开头,重启一行,刷新缓冲区
  • /n:重启一行

C++同时支持两种换行方式

字符串

两种字符类型

  • C++ 有两种风格的字符串
  • 字符串都要放在""中
  1. C语言风格的字符串
    char 变量名[]=“字符串值”

char cat[8]={'a','s','f','/0'} ;  //如果逐个字符的赋值,最后一定要加上/0(空字符)

//更为简单的方法
char bied[11] = "MY right";  //直接双引号一个字符串,不需大括号。

cin >> bied ;  //字符串的输出

  1. C++ 风格的字符串
    string 变量名=“字符串”
  • 要用string型的字符串要添加一个#include< string >的头文件

string类的操作

  • string类可以通过+运算符,把两个字符串来接起来

  • 不能将一个字符数组赋给另一个字符数组,但是string可以

  • 使用函数strcpy()将字符串复制到另一个数组中,原数组会被覆盖掉
    strcpy(charr1,charr2); //把charr2复制给charr1

  • 使用函数strcat()可将字符串添加到另一个数组后面
    strcat_s(a1, a2);

  • strcat()可能会因为数据的申请空间不够,而导致覆盖相邻内存,导致程序终止。但string类具有自动调节大小的功能。

  • length(),strlen(),size(),sizeof()

  • length()只是用来计算字符串中申请内存空间的长度。

  • size()函数与length()函数作用相同,在C++中。

  • sizeof()运算符用来求对象申请内存空间的大小(char a[20] 表示申请了20个字符空间)

  • strlen()用来计算字符串的长度(不包括空字符),储存数据的长度,参数为字符指针


 char a1[20] = "abcd";
   string a2 = "qwer";
   int b1=strlen(a1);  //  b1 = 4
   int b2=size(a1) ;	//	b2 = 20
   int b3=sizeof(a1);	//	b3 = 20
   
   int c1 = strlen(a2.c_str());	//c1 = 4
   int c2 = size(a2);		//c2 = 4
   int c3 = sizeof(a2);	//c3 = 28

4.输入输出

4.1 命名空间

有输入输出的函数需要加上using namespace std;命名空间,就可以直接使用cin,cout不用加上std::的前缀。

4.2 输入cin

语法:cin >> 变量名

int a = 0;
cin >> a;

floar f;
cin >> f;

char ch;
cin >> ch;

string str = "hello" ;
cin >> str ;

int c ;
double d ;
cin >> c >> d; // 连续命名

  • 当给布尔类型赋值
 bool flag = false;
 cin >> flag;
 只要赋值不是0bool类型的值都是真

4.3 输出cout

  • 语法 cout <<" ";
  • 连续输出 cout <<内容<<内容<<内容;
cout <<"hello word";   //输出字符串
cout << 12.12;         //输出数字
cout<<'d';             //输出字符

cout << "hello word"<<12.12 << 'd'; // 连续输出

4.4 面向行输入getline()

geline()函数读取整行通过回车键换行来确定结尾会读走并删除换行符

  • getline函数有两个参数,1.数组名,2.参数要读取的字符数(个数包括换行符)
cin.getline(name,20);  
  • geline函数每行通过换行符结尾,但是不保存换行符并用空格替换,由于空格站一位,所以参数是20,最多读取19个字符

4.5 面向行输入get()

iostream类的另一个函数,工作方式与getline类似,连个参数,但是get函数将换行符留在输入的队列

cin.get(name,20)
  • 由于get函数将换行符留在输入的队列中,当两连续的cin.get(name,size)同时出现时,由于第一个输入行的结尾保存的换行符,是的第二个输入结束输入,所以第二个输入,无法有效运行,可以用cin.get()来读取第一个中的换行符。
cin.get(name, ArSize);
cin.get(desert, ArSize);

解决后:

cin.get(name, ArSize);
cin.get();
cin.get(desert, ArSize);

// 另一种使用方法是将连个合并
cin.get(name, ArSize).get();   // 效果相同
  • cin.get()该函数只能读取一个字符。
  • cin.getline()也能读取换行符,但是使用get()的比较多
  • 当输入的字符大于费分配的空间长度,get()与getline()将把多余的字符留在输入队列中,getline()还会设置失效位,并关闭后面的输入。

5.命名空间 namespace

  • 作用: 区别相同的变量和函数
  • 放在main函数外
  • 定义格式:
    namespace 空间名
    {
    
    }// 最后这里有无;都可以
    
  • 调用格式
    空间名::空间中的函数(变量)名;
    

当一个程序中有两个相同的变量、函数或其他的什么,可以定义两个不同的命名空间,不两个相同的变量分别放在两个命名空间里

 namespace pace1  
  {
    void sort()
    {

    }
  }
  namespace pace2  //定义
  {
    void sort()
    {
      
    }
  }
pace1::sort();  //调用
pace2::sort();  //调用

6.结构体

  • 与C语言结构体大致相同,细节上有些区别
  1. 声明变量可以不用struct关键字
#include <iostream>
using namespace std;
struct node  //  定义一个node类型的结构体
{
  int m;
}
int main()
{
  node a;         // 定义了一个node类型结构体,结构体名字为a.
  struct node a;  //C语言需要用在node前要加一个struct关键字
}
  1. C++可以再结构体里面放函数,C不可以,不过C可以放函数地址
struct node  //  定义一个node类型的结构体
{
  int m;
  void fun()   //C++允许在结构体里面放函数
  {
    cout<<"hahaha";
  }     
}

7. new和delete

  • new 空间申请,类似于malloc
  • delete 空间释放,类似于free

单个空间的申请


int *p=(int*)malloc(sizeof(int));  //C语言的malloc申请款空间

int *p1=new int// C++的new申请款空间  //new type,type的类型一定要与定义的匹配
delete p1;  //删除空间 直接把想要删除的地址写上

int *p2 = new int(121)//空间申请的时候可以直接初始化

int *p2 = new int*p2 = 121;             //也可以分布赋值

数组空间的申请


int *p = malloc (4*5);  //C语言的malloc申请款数组空间
int *p2 = new int[5] ;  //C++的new申请款空间

delete [] p2;  //数组释放的时候要加[]

  • 由于C++没有在给数组申请空间的初始化,可以用 memset

memset

可以为各种类型的新申请的空间进行初始化.

  • 由于她是直接为内存进行操作,所以memset可对一些数据量很大的结构体,数组赋值速度很快
int stu[10];
int *p=stu;
memset(stu,1,sizeof(stu));  // stu数组中的是就都会被赋值为1。

指针空间的申请


int* ps = new int;
delete ps;

int* psome = new int [10];
delete [] psome ;  // 释放数组指针空间的时候一定要加[],表示要释放整个数组,而不是指针指向的元素。

注意

  • 单个元素的释放是delete p,数组空间的释放是delete [] p,一定要匹配的去释放,不匹配的释放,结果是不一定的。
  • 不要使用delete释放已经释放的内存块
  • 不要使用delete释放已经释放不是new申请的内存
  • 不要创建指向用一个内存的指针
  • 如果使用new[ ] 分配内存,应该使用delete[ ]来释放

自动存储、静态存储、动态存储

  • C++有两种存储方式:自动存储、静态存储、动态存储

自动存储

在函数内部定义的常规变量使用自动存储空间,意味着他们在被所属函数调用时自动产生,函数结束自动释放

静态存储

整个程序执行的过程中都存在的存储方式,是变量变为静态的方式是1.在函数外定义它2.申明变量的时候加上staticstatic double fee=45.3;

动态存储

new和delete运算符就提供了一种更加灵活地内存管理方式,这种称为自由内存管理方式或

8. 引用(&)

C++新增的一种复合类型,给已定义的变量取一个别名,两者用法相同。

  • 引用和原变量的值和地址相同

int a =10;  //定义一个变量a
int &c=a;   //&符号放在定义时,不是取地址,而是引用。
            //声明a的一个引用,c是a的一个别名
            //a与c的地址是相同
     
  • 对引用和原变量操作两者都会改变

	int ratss = 123;					
	int& rodentss = ratss;		

	cout << "ratss=" << ratss<< endl ;				// ratss=123
	cout << "rodentss=" << rodentss << endl;	// rodentss=123   两者的值相同  
	
	// 对引用改变,二者都改变
	rodentss++;
	cout << "ratss=" << ratss << endl;					// ratss=124
	cout << "rodentss=" << rodentss << endl;		// rodentss=124
	
	// 对源数据改变,二者都改变
	rats++;
	cout << "ratss=" << ratss << endl;					// ratss=125
	cout << "rodentss=" << rodentss << endl;		// rodentss=125  对其中的一个进行++操作另一个值也会改变
	// 二者地址相同
	cout << &ratss << endl;			// 	010FFD38
	cout << &rodentss << endl;	//	010FFD38  两个地址相同
	return 0;

  • 引用与指针不同

	int ratss = 123;
	int& rodentss = rats;  
	int* p = &ratss;
	
	//三者的值相同
	cout << "ratss=" << ratss << endl;				//ratss=123
	cout << "rodentss=" << rodentss << endl;	//rodentss=123
	cout << "*p=" << *p << endl;							//*p=123
	
	//三者地址相同
	cout << "&ratss=" << &ratss << endl;				// &ratss=003EF6F4
	cout << "&rodentss=" << &rodentss << endl;		// &rodentss=003EF6F4
	cout << "p=" << p << endl;								// p=003EF6F4

  • 可见:ratss(原变量) rodentss(引用) *p(指针) 三者等价,&ratss与&rodentss与p 三者等价

  • 引用必须在初始化的时候进行赋值,但是初始化之后还可以引向其他的值

   int rat;
   int & rodent = rat ;    可以

   int & aban;
   aban = rat;    不可以

   int temp =100 ;
   int & opt = temp;
   int str = 50;
   opt = str;       可以 相当于赋值
   
  此时 temp opt  str 三者的是都为50
  temp opt 的地址依然相同,与str的地址不同

常量的引用


int &a=12;  //会报错
const int &a=12;  //可以这样修改

数组的引用

  • 数组的引用一定要把&和引用名加上()

int arr[12];
int (&p)[12]=arr; //一定要加()

int arr2[2][3];
int (&p2)[2][3] = arr2;

引用做函数的参数


void swapv(int a,int b)
void swapp(int & a,int & b)
void swapr(int *p,int *q)

// 三个函数的功能都是交换形参的值,就是形参的形式不同
int main()
{
  int wallet1 = 100;
  int wallet2 = 50;
  
  //参数为原型,无法交换值
  void swapv(wallet1,wallet2);
  cout << wallet1 << wallte2 ;
  
  // 参数为引用,可以交换
  void swapp(wallet1,wallet2);
  cout << wallet1 << wallte2 ;
  
  // 参数为指针,可以交换
  void swapr(&wallet1,&wallet2);
  cout << wallet1 << wallte2 ;


  按值传递参数的函数,输出没有交换两个值;
  但是引用和指针方法都成果的交换了两个值

}

注:

  1. 按值传递函数swapv中变量a,b是复制的wallet1,wallet2的值的新变量,交换a,b的值并不会影响wallet1,wallet2的值
  2. 按值传递和按引用传递看似是,但是地址运算符&是的其按地址传递参数
  • 如果想让****,同时又想使用引用可以使用常量引用,在函数原型和函数头使用const
    double refcube (const double &ra);
    当要修改ra的时候,就会发生错误
    

按值传递与按引用传递

  • 按值传递一下都是正确的
     double z=cube(x+2.3);
    
     z=cube(8.0);
    
     int k=10;
     z=cube(k);
    
     double yo[3]={2.2,3.3,4.4};
     z=cube(yo[2]);
    
    
  • 按引用传递参数时就不能将算数表达式传递给函数了。

对于形式参数为const引用的C++函数,如果实参不匹配,则其行为类似于按值传递为确保原始数据不被改变,将使用临时变量来储存。
如果函数调用的参数不是左值或与相应的const引用参数的类型不匹配,则C++将创建类型正确的匿名变量,将函数调用的参数的值传递给匿名变量,并让参数来引用该变量。

  • 尽可能使用const参数引用参数为常量数据
  1. 使用count可以避免无意中修改数据。
  2. 使用const是函数,能够处理const和非const的实参,否则只能接受非const的数据。
  3. 使用const引用,使函数能够正确生成并使用临时变量

引用结构体

  • 声明结构体的时候要加&,定义结构体的时候不需要加&

引用与指针的区别

  1. 引用声明要初始化,指针不用
  2. 引用初始化后就不能再引用其它空间,指针还可以指向其它空间
  3. 引用不占内存空间,指针占空间
  4. 引用效率更高(引用是对内存空间的直接操作,指针装的是地址,通过地址操作空间)
  5. 引用更加安全,指针可能偏移(指针可以做加运算指向下一个地址)
  6. 指针更加灵活,直接操作地址,C与C++都可以

9. 增强for循环

10.函数

函数的参数

  • 函数在定义形式参数的时候如果要在定义的时候形式参数赋值,就要从右向左连续赋值。(把要赋值的放在右边)

void abu(int a, char'b',floar f=123.23)  //从右向左连续的都是赋值的
{

}

函数的重载

函数名相同,参数不同(参数的类型、个数)的函数互为重载函数


void fan(int a)
{

}
void fan(int a, int b)
{

}
void fan(char c)
{

}
// 系统会自动根据要调用的参数的形式和个数调用相应的还是

内联函数

编译代码与其他程序代码关联起来,就是编译器将使用相应的函数代码替换函数调用。相当于#define,但是相较于#define更加安全

  • 声明函数时是加关键词 inline
# include <iostream>
using namespace std;

inline double square(double x) { return x * x; }

int main()
{
	double a = 3;
	double b = square(a);  
	cout << b;
}
// 输出b为9,调用square(a),就用定义函数的函数体a*a来替换a

inline工具是C++新增的特性,C语言使用预处理器语句,#define提供宏。

默认参数

在定义函数时给形参赋值,该值为默认值,如果在调用函数时,对应的实参有值就用实参的值覆盖,默认值如果没有给实参赋值,就用默认值代替实参的值

int harpo (int n,int m=4,int j=5);
// 该函数的m和j就是默认参数。
  • 默认参数必须全部依次排列在右边
  • 实参也要按照形参的对应顺序调用的时候 不能中间跳过参数 beeps=harpo(3, ,8)这样不行。

函数 模板

当函数需要改变函数的参数类型,但是又不想,总是重复的定义相似的函数,把某些变量的类型当做变量,在调用的时候再输入具体想要的变量类型。

创建一个函数模板


template <typename T>
void Swaps(T& a, T& b)
{
	T temp;
	tmep = a;
	a = b;
	b = temp;
}
//函数为void类型,所以没有返回值,如果有返回值要写

这个函数是交换两个参数的值,其中template和typename是固定的T代表着你要输入的函数返回值类型,输入完函数类型之后,函数体中的T用函数类型替换。

  • 函数模板的实例化:隐式实例化、显示实例化

template <typename T>
T Maxs(T a, T b)    // 该函数有返回值,返回值类型为要输入的类型,用T先代替
{
	return a > b ? a : b;
}
int main()
{
  // 函数模板的隐式实例化,由编译器去猜测函数模板的类型。
	int n = Maxs(1, 4);
	cout << n;
	float m = Maxs(2.3f,4.0f);
	cout << m;

  // 函数模板的显示实例化,在函数后面用的<>中表明出来 
	double d = Maxs<double>(3, 4.5f);
	cout << d;
}

11.数组

  • C++与C的数组基本相同

int carrds[4]={3,6.8,4};
int hard[4];
hard[1]=2;
hard[2]=3;
hard[4]={2,3,4,5};  //不允许,只有在定义的时候可以这样用大括号赋值

double earn[4]={};  //如果大括号里为空,则把所有值都初始化为0

vector模板类(一种动态数组)

vector类似于string类,是一种动态数组。

  • 使用new创建动态数组的替代品,使用new和delete来管理内存,但这种是动态的。
vector<int>vi;

array模板类

12.结构体

定义与C语言相同
与C语言不同的是C++在定义一个结构体的时候不需要写struct


struct inflatable 
{
  char name[10];
  double volum;
  int price ;

};

// 与C语言不同的是C++在定义一个结构体的时候不需要写struct

int main()
{
   inflatable guest=
  {

  };
  // 虽然不用写struct但是建议写上,提高阅读效率
   inflatable pal=
  {
		"Glorious",
		3.12,
		33.4
  };
}

  • 定义初始化结构体的时候,如果大括号里为空,则所有被赋值为0

13.共用体(union)

共用体是一种数据格式,它能够存贮不同的数据类型(只能储存int, long,double类型)
语法与结构体相似


union one4all
{
  int int_vall;
  long long_vall;
  double double_vall;
}

one4all pail;  //定义一个one4all类型的数据
pail.int_vall=15;
cout << pail.int_vall;

14.指针

  • 指针是一个变量,他储存的是值的地址而不是值本身
  • 一定要在指针应用解除引用运算符*之前(定义指针的时候),将指针初始化为一个确定的、适当的地址,这是使用指针的金科玉律
  • 指针在32位操作系统中占4个字节,64位中占8个字节
    C风格的指针:
+ int *p;  // 强调*p是一个int类型的值

C++风格的指针

+ int* p; // 强调int*是一种数据类型——指向int的指针

C++会将数组名解释成为第一个元素的地址


double wages[3]={123,345,456,};
double* pw = wages; //指针保存的是地址值,应为&wages,但C++会将数组名解释成为第一个元素的地址,就不用加&了。

  • 指针加一,指向下一个地址,增加的是一个数据类型所占的字节数

空指针是不能被访问的:
空指针:int * p = null,p就是空指针

野指针:指针指向一个非法的空间。

空指针和野指针都不是我们自己申请的地址,不要随意访问他

结构体指针

struct student
{
	string name ;
	int age ;
};

int main()
{
	student s = {"张三"18 }
	// 结构体指针
	student* p = &s ; 
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值