C++ primer plus(第6版中文版)小知识点笔记一(衔接C语言部分)

1、using编译命令

1、将using namespace std 放在函数定义之前,让文件中所有函数都可以使用名称空间std中的所有元素;
2、将using namespace std 放在函数定义中,让该函数可以使用名称空间std中的所有元素;
3、在特定函数中使用using std::cout ;这样的编译指令,而不是using namespace std,让该函数可以使用指定的元素,如cout;
4、完全不使用编译指令using,而在需要使用名称空间std中的元素时,使用前缀std::,例如
	std::cout << "Chinese" << std::endl;

2、结构体

1、C++允许声明结构变量时省略关键字struct;
2、与C不同,C++结构除了成员变量之外,还允许成员函数,但这些高级特性通常用于类中;

3、声明和初始化指针

3.1、声明指针

1int *ptr 和 int* ptr; 都是可选的,前者表示*ptr是int类型,而后者表示ptr是int* 类型
2int *ptr1,ptr2; 前者表示创建int类型指针,而后者表示创建int变量

3.2、初始化指针
指针可以先声明在初始化,也可以声明和初始化一起

int value = 10;
int *ptr1;
ptr1 = &value;			//先声明再初始化
int *ptr2 = &value;		//声明和初始化一起

3.3、注意
指针可以指向不同类型的变量、函数、结构体等等

1int *ptr1;
2double *ptr2;
3char *ptr3;
4struct student *ptr4;

但是指针变量本身的长度通常都是相同的,和系统相关

4、什么是OOP

OOP(object oriented programming) 面向对象编程

OOP强调的是在程序运行阶段(而不是编译阶段)进行决策,该属性提供了灵活性,可以根据实际情况进行调整。变量是在编译时分配的有名称的内存,而指针只是为可以通过名称直接访问的内存提供了一个别名。指针真正的用武之地在于,在运行阶段分配未命名的内存以存储值

5、new和delete用法

5.1、分配和释放单变量

1、typeName *ptr_name = new typeName;
int *ptr1 = new int;				//开辟内存
delete ptr1;						//释放内存
2、typeName *ptr_name = new typeName(value);
double *ptr2 = new double(66.66);
......

5.2、分配和释放一维数组空间

typeNmae *ptr_name = new typeName[num];		//且num值不必在编译时确定,可以在运行时确定
int *ptr = new int[10];		//数组长度为10的动态数组
delete []ptr;

5.3、分配和释放二维数组空间
在此之前需要了解二维数组的本质:其实也是一维数组,只是这个一维数组的元素类型也是一维数组。

int array[a][b] == int array[][b] == int (*array)[b];
array为数组名,该数组有a个元素,每个元素都是一个数组,且有b个int值组成
eg:int arr[2][3];			//数组长度为2,元素类型为int[3]的一维数组

上述二维数组会被编译器视作一个元素类型为‘int[b]’的一维数组,该数组长度为a。
二维数组的动态创建:

1、使用常量创建
int (*arr1)[b] = new int[a][b];			//创建数组,其中b一定要为常量
理解:arr1为int*指针,指向一个长度为b、类型为int的数组
delete []arr;							//释放内存
2、使用指针间接引用
int **arr2 = new int*[a];				//创建
for(i=0; i<a; i++)
{
	arr2[i] = new int[b];
}
/*----------------------------*/		//释放
for(i=0; i<b; i++)
{
	delete []arr2[i];
}
delete []arr2;

具体参考:创建二维数组1创建二维数组2

5.4、注意

1、delete释放内存,只会释放指针指向的内存,但是不会删除指针变量本身,也就是说还可以重新指向别的内存;
2、一定要配对的使用new和delete,否则可能发生内存泄露;
3、不用对已经释放的内存重复释放,会导致无法预估的危险;
4、 5.2一维数组中的两式中方括号是非常重要,两者必须配对使用,如果delete语句中少了方括号,因编译器认为该指针是指向数组第一个元素的指针,会产生回收不彻底的问题(只回收了第一个元素所占空间),加了方括号后就转化为指向数组的指针,回收整个数组,delete的方括号中无需填数组元素数,系统自己知道,写了编译器也忽略。

5.5、实例

利用new和delete,根据输入的字符串动态的申请内存,避免直接使用数组存储大量数据,浪费内存。

int main()
{
    char * name;        // create pointer but no storage

    name = getname();   // assign address of string to name
    cout << name << endl;
    delete [] name;     // memory freed
	return 0;
}

char * getname()        // return pointer to new string
{
    char temp[80];      // temporary storage
    cout << "Enter last name: ";
    cin >> temp;
    char * pn = new char[strlen(temp) + 1];
    strcpy(pn, temp);   // copy string into smaller space

    return pn;          // temp lost when function ends
}

6、指针常量和常量指针

const int *ptr1;			//常量指针:指针指向可改,但指向的内容不可改
int *const ptr2;			//指针常量:指针指向不可改,但指向的内容可改

C++禁止将const地址赋给非const指针,但是非const指针可以赋给const指针

1const数据的地址只能赋给const指针
	const int value1 = 100;
	int *ptr1 = &value1;				//invalid
	const int *ptr2 = &value1;			//valid
这是因为如果可以通过指针修改value值,会使得将value定义为const显得荒谬

2int value2 = 100;
	int *pt3 = &value2;					//valid
	const int *ptr4 = ptr3;				//valid,但是不能通过指针修改内容
//上述为一级间接关系,全部合法
3、对于数据本身不是指针的数据,可以将const数据或者非const数据的地址赋给指向const的指针
	int value3 = 100;
	const int value4 = 100;
	const int *ptr5;
	ptr5 = &value3;						//valid
	ptr5 = &value4;						//valid

参考链接

7、C++管理数据内存

三种方式:自动存储、静态存储、动态存储

1、	自动存储:函数内部定义的常规变量,被称为自动变量(局部非static变量)
	一般在所述函数被调用自动产生,函数调用结束时消亡;
	通常存储在栈中;

2、	静态存储:分为全局变量和static变量
	通常放在全局区
(后序更新)

3、	动态存储:使用new分配,存储在堆中;

8、读取数字的循环

情境:定义了一个整型数组,但是输入了char数据:会出现下面情况:

1、n的值保持不变;
2、不匹配的输入将被留在输入队列中;cin对象中的一个错误标记被设置;
3、不匹配的输入将被留在输入队列中;cin对象中的一个错误标记被设置;
4、对cin方法的调用将返回false(如果被转换为bool类型)

因此在输入错误之后回返回false,可以用做退出循环的标志,且错误标记要重置,才可以继续输入,使用cin.clear()重置。

int Max = 5;
int golf[Max];
    cout << "Please enter your golf scores.\n";
    cout << "You must enter " << Max << " rounds.\n";
    int i;
    for (i = 0; i < Max; i++)
    {
        cout << "round #" << i+1 << ": ";
        while (!(cin >> golf[i])) {
            cin.clear();     // reset input
            while (cin.get() != '\n')
                continue;    // get rid of bad input
            cout << "Please enter a number: ";
        }
    }

输入数字则返回true,!(cin >> golf[i])为false,结束此次循环,输入字符时,!(cin >> golf[i])为true,进入内部循环,首先使用cin.clear()重置标志位,在while中使用cin.get()读取换行符之前的所有输入,从而删除这一行的错误输入!

9、函数

9.1、函数三要素

1、函数声明(函数原型)
2、函数调用
3、函数定义

对于函数声明:是为了告知编译器:函数返回值类型、参数类型和数量(可以不包含参数变量名,但定义中必须包含);
对于函数调用:使用该函数的接口;
对于函数定义:函数的具体功能实现;

9.2、函数和一维数组

将数组作为参数传递给函数的用法:实质上是将数组名视为指针。

1void func(int array[],int len);
2void func(int *array,int len);
/*-----------------------------*/
1void func(int array[],int len)
{
	//可以直接使用数组表示法
}
2void func(int *array,int len)
{
	//可以直接使用数组表示法
}

上述对数组的操作,在函数中会对原始数组进行修改,为了防止无意修改,在声明时可以使用const关键字

9.3、函数对数组指定区间操作

int array[20] = {......};
void func(int *arr_begin,int *arr_end);		//声明
func(array+5,array+10);
void func(const int *arr_begin,const int *arr_end)
{
	const int *ptr;
	for(ptr = arr_begin; ptr <= arr_end; ptr++)
	{
		//operation
	}
}

9.4、函数和二维数组

1void func(int array[][b],int len);
2void func(int (*array)[b],int len);int (*array)[b]理解为一个指向由b个int数据组成数组的指针,具体查看上述5.3二维数组的本质
此时只规定了数组的列数,没有规定行数,所以传入第二个参数len表示数组的行数
/*-----------------------------*/
1void func(int array[][b],int len)
{
	//可以直接使用数组表示法
}
2void func(int (*array)[b],int len)
{
	//可以直接使用数组表示法
}

10、函数与字符串

10.1、字符串做函数参数
字符串作为参数来传递时,实际传递的是字符串中第一个字符的地址,即char*

void str_func(const char * str,char ch);
char t_str[] = "aabbccddeeffgghh";
str_func(t_str,'b');

11、函数指针

11.1、获取函数地址

函数地址即函数名:
1function1(func1);				//传递的是函数地址
2function2(func2());				//传递的是函数返回值

11.2、声明函数指针

1、先写函数原型:
double func(int value);						//函数原型
2、使用(*p_fun)替换函数名就是指向该函数的指针
double (*p_func)(int value);				//声明函数指针

参考函数指针和指针函数

结束!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值