您的当前位置:首页正文

后端开发核心技术 第1章 C++编程常用技术

2024-11-30 来源:个人技术集锦

1.1第一个C++程序

1、include 这不是一个C++语句,是一个预处理语句。include一个文件,就是把这个文件所有内容都加进来

3、include和include<iostream.h>是不一样的,后缀位.h的头文件在C++标准中硬件不再支持。当使用include<iostream.h>时,相当于在C中调用库函数。换句话说iostream是iostream.h的升级版,但是string不是string.h的升级版

1.2函数

1、定义函数的一般格式是

返回值类型  函数名([形参]{
	函数体
}
注意区分实参和形参

2、函数重载

C++允许用同一函数名定义多个函数,但是这些函数必须参数个数不同或者类型不同。

3、函数模板

建立一个通用函数,其函数类型和形参不具体指定,而用一个虚拟的类型来表示,这个通用函数就是函数模板
一般格式
template
例子

#include<iostream>
using namespace std;
template<typename T>
T min(T a,T b, T c)
{
	if(a > b) a = b;
	if(a > c) a = c;
	return a;
}
int main()
{
	int a = 1,b = 2,c = 3;
	cout<<min(a,b,c)<<endl;
	long long a1 = 10000000000,b1 = 200000000000,c1 = 30000000000;
	cout<<min(a,b,c)<<endl;
	return 0;
}

1.3数组

1、数组的定义:相同类型数据的集合。

int a[10] = {1,2,3,4,5,6,7,8,9,10};

2、字符数组

char str[10] = "Book"

其中str是一个字符数组,并且str[0]=‘B’…C++中用 \0 来表示一个字符串的结束,这里str[4] - str[9]都是 \0。

strlen和sizeof区别

strlen(str) = 4
sizeof(str) = 10
strlen是函数,在运行时才计算,以\0结尾
sizeof是运算符,不是一个函数,在编译时间已计算好

sizeof用法:
1)数组 编译时分配的数组空间大小
char a[10] = “hello”
因为char占1Byte,所以sizeof(a)的值是10*1 = 10Byte
2)指针
一般大小与编译器有关,32位机器一般为4
3)类型
int b = 10
在32位机器上,int占4Byte,所以sizeof(b) 的值位4Byte
4)对象

class Class_Sample
{
	int a,b;
	int func();
}Class_a;
两个int型站8Byte,所以sizeof(Class_a)的值位8Byte。
5)函数
函数的返回类型所占的空间大小,且函数的返回类型不能为void

1.4指针

指针的概念:

int p1 = 1;
int *p2;
p2 = &p1;//p2指向p1
p1 = 2;//*p2的值也是2
*p2 = 3;//p1的值也是3

数组和指针:

1)数组指针,也称行指针
二维数组复制给数组指针

int a[3][4];
int (*p)[4];//顶一个数组指针,指向含4个元素的一维数组
p = a;//将二维数组的首地址给p
p++;//执行完之后,p = p + 1,p跨过行a[0][]指向a[1][]

2)指针数组
如果将二维数组复制给指针数组

int*p[3];
int a[3][4];
for(int i = 0;i < 3;++i)
{
	p[i] = a[i];
}

int p[3]表示一个一维数组存放3个指针变量,分别是p[0]、p[1]、和p[2],所以分别进行赋值
表示第i行第j列的元素,可以用
p[i][j] 、
(p[i] +j)、(((p+i)+j)、((p+i))[j]

3)字符串和指针

char str[] = "I am a progreammer";//字符数组
char *str1 = "abc";//字符指针变量,指向一个字符串
char* str2[] = {"hello world","good bye"};//字符指针数组,可以存放多个字符串
string str3 = "I am a progreammer too";//字符串变量
cout << str << str1 << str[0] << str3;

4)函数和指针
指针变量指向函数

int func(int a);
int (*f)(int a);//声明一个函数指针
f = &func; 

数组和指针的区别:

1.5引用

1)引用的定义:别名

int a = 2;
int &r = a;//r是变量a的引用,a和r占用同一存储单元。
a = a + 4;//r和a都变成了6

2)引用作为参数

将一般变量作为函数的参数,传给形参的是变量的值,执行期间形参的值改,并不会传回给实参。因为在调用函数时,形参和实参不是一个存储单元
将引用传递函数的参数时,在内存中没有产生实参的副本,是直接对实参进行操作。当参数传递的数据较大时,用引用的效率高,占用空间小

void Main(int a,int b){...}
void Main(int &a,int &b){...}

3)常引用
不能通过引用对目标变量的值进行修改

const 类型标识符 &引用名 = 目标变量名

int a = 10;
const int &r = a;
r = 1;//错误
a = 1;//正确
string func1(){...}
void func2(string &s){...}

//下面都是非法的
func2(func1());
func2("hello");
原因是func1()和“hello”都将产生一个临时对象,在C++中,这些临时对象都是const类型的。上面的表达式试图将一个const类型转换成非const类型
**引用参数应该在能被定义为const类型下,尽量定义为const**

1.6结构体、公共体、枚举

1)结构体 struct

结构体 注意对其

struct 结构名
{
	数据类型 成员名;
	数据类型 成员名;
	......
};
struct B
{
	char a;
	double b;
	int c;
}
//1 + 7(对齐) + 8 + 4 + 4(对齐) = 24

2)共用体 union

union共用内存,以最长的为准,注意对其

union 共用体数据名
{
	数据类型 成员名;
	数据类型 成员名;
}
union A
{
	int a[5];
	char b;
	double c;
}
//sizeof(A)不是20,而是24,要以最长的double(8 byte)对其

3)枚举 enum

enum 枚举类型名{枚举常量表列};

1.7预处理

1、常用宏定义声明格式

//简单的宏定义
#define 宏名 字符串
#define PI 3.1415926

//带参的宏定义
#define 宏(参数列表) 宏
#define A(x) x 

.1)不加括号容易引起错误和误用

#define N 2 + 9
int main()
{
	int a = N * N;
	cout << a << endl;
	return 0;
}
//结果是 29;
//因为被展开成 2 + 9 * 2 + 9
//加上括号就好
#define N (2 + 9)

2)带参也容易引起错误

#define area(x) x*x
int mian()
{
	int y = area(2 + 2);
	cout << y << endl;
	return 0;
}
//结果是8
//展开成2 + 2 * 2 + 2;
//加上括号
#define area(x) (x * x)

2、do…while(0)的妙用

主要是在展开时间保持初始的语义。
#define Foo(x) do{\
	statement one;\
	statement two;\
}while(0) //这里无分号

//如果不用do while
#defineFoo {\
	statement one;\
	statement two;\
}

if(condition)
	Foo(x);
else
	...;

如果使用的是第二种Foo,变成
if(condition)
	statement one;
	statement two;
else
	...;
//出现错误,加了do while可以保持初始的语义。

3、条件编译

作用:当标识符已经被定义过(一般用define),则对程序段1进行编译,否则编译成语段2,**其中else部分也可以没有。**
#ifdef 标识符
	程序段1
#else
	程序段2
#endif


#ifdef 标识符
	程序段1
#endif

//下面当表达式非0则编译程序段1,否则编译程序段2
#ifdef 表达式
	程序段1
#else
	程序段2
#endif

例子

#define __DEBUG__

int main()
{
	int x = 10;
	#ifdef __DEBUG__
		cout << "FILE" << __FILE__ <<",LINE" << __LINE__ << ",x:" << x <<endl;
	#else
		printf("x = %d\n",x);
	#endif
	return 0;
}

4.extern "C"的应用

#ifdef __cplusplus
	extren "C"{
#endif
	...
#ifdef __cplusplus
}
#endif

其中__cplusplus是C++的预宏定义,表示当前的开发环境是C++。C++中支持重载,通常对函数名字进行处理(为函数名改编),而在C语言中,只是简单的函数名字,不加如其他信息。

int func(int demo);
int func(double demo);

C语言无法区分上面两个函数,都是_func,而C++中两个名字可能是_func_Fi和_func_Fd,区分两个函数。
所以在C/C++混编,extern “C”表示当前这段代码用C标准编译,保持C++与C的兼容性

#include<stdio.h>
int main() {
    #define TO_LITERAL(text) TO_LITERAL_(text)
    #define TO_LITERAL_(text) #text
    #ifndef __cplusplus
    /* this translation unit is being treated as a C one */
        printf("a C program\n");
    #else
       /*this translation unit is being treated as a C++ one*/
        printf("a C++ program\n__cplusplus expands to \""
          TO_LITERAL(__cplusplus) "\"\n");
    #endif
    return 0;
}

程序运行结果,因为定义了__cplusplus,所以执行else
a C++ program
__cplusplus expands to "1"

如果没有定义__cplusplus,当前代码当作C原代码处理,如果定义了__cplusplus,当成C++的源代码处理,并且输出__cplusplus宏被展开后的字符串

显示全文