c++primer笔记(前6章)

本文详细介绍了C++中的指针、const、constexpr、类型别名、auto、decltype、数组、左值/右值、sizeof、无符号类型、const形参、数组形参、函数指针重载等概念,并探讨了函数声明、函数指针的使用和返回、以及C++primer中的相关内容。
摘要由CSDN通过智能技术生成

1 指针和const

值为常量,则其绑定的指针/引用不能改变他的值。

2 const指针

常量指针:常量指针必须初始化,并且一旦初始化,其值(绑定的地址)不能再改变。int const *p或者const int *p。指向的内存地址可以改变,但是不可以改变所指内存地址的值。
指针常量:(*放在const之前表明指针是一个常量)即不变的是指针本身,而非指向的那个值。如int *const p = &i,p是一个指针常量,不能改变p绑定的地址,但是可以改变p所指向对象的值。

3 顶层const

顶层const表示指针本身是一个常量。底层const表示指针所指对象是一个常量。int i=0;int *const p = &i表示指针常量,指针p1的值不能改变,是一个顶层const。const int ci = 1; const int *p2 = &ci,常量指针p2,表示p2所指对象的值不能改变,但p2可以改变,是底层const。又如const int *const p3 = p2,左侧const是底层const,右侧const是顶层const。
const int ci = 1;const int &r = ci,用于声明引用的const都是底层const。

4 常量表达式

指值不会改变并且在编译过程就能得到计算结果的表达式。①字面值是常量表达式②常量表达式初始化的const对象也是常量表达式。const int a = 20(是),int b = 30(否),cosnt int c = getsize()(否)

5 constexpr变量

声明constexpr的变量一定是一个常量,而且必须用常量表达式初始化。constexpr int f= 20(是),constexpr int ff = f+1(是),constexpr int sz = size()(当size函数是constexpr 函数时是)
一个constexpr 指针的初始值必须是null或0;

6 指针和constexpr

constexpr 仅对指针有效,对指针所指对象无关。const int *p = NULL;p是指向常量的指针。constexpr int *q = NULL,q是常量指针。因为constexpr 把定义的对象置为了顶层const。
constexpr 既可以指向常量也可以指向非常量(p60)

7 类型别名

① typedef:typedef double wa,*p,wa是double的同义词,p是double*的同义词。
②using:using a = Sales_items,a是Sales_items类型。

8 auto

auto类型说明符,能让编译器去分析所属的类型。auto定义变量必须有初始值。auto一般会忽略掉顶层const,同时底层const会保留下来。const int ci = 1;auto &g = ci;g是一个整形常量引用。
auto &h = 2(错误),const auto &h = 2(正确)

9 decltype类型指示符

它的作用是选择并返回操作数的数据类型。decltype(f()) sum = x,sum的类型就是函数f的返回类型,但是不会指向f函数,只会根据f的返回类型推断出sum的类型。
dcltype和auto的不同:若decltype使用的表达式是一个变量,则decltype返回该变量的类型(包括顶层const和引用在内)const int c = 0,&cj = c;decltype(ci) x = 0;decltype(cj) y = x;decltype(cj) z;(错误,z必须初始化-引用类型必须初始化),x类型是const int,y类型是const int&,y绑定到x。
int i=1,*p=&i,&r=i;decltype(r+0) b;(正确);decltype(*p) c;c是int &类型,必须初始化。
这里是引用int i =1;decltype((i)) d;d是int& 必须初始化。decltype(()),双括号的结果永远是引用。

10 数组

char a[2] = "as";(错误,没有空间存放空字符)int *p[10];p是含有10个整形指针的数组。int &p[10] = ...(错误,不存在引用的数组)int (*p)[10] = &arr;p指向一个含有10个整数的数组。int (&p) [10] = arr;p引用一个含有10个整数的数组。int *ptr[10];int *(&p1)[10] = ptr;,p1是一个引用,引用对象是大小为10的数组,数组的元素是指向int的指针,p1就是一个含有10个int型指针的引用。

11 ptrdiff_t

两指针相减结果是 ptrdiff_t的标准库类型,差值可能为负,因此它是带符号类型数据。

12 左值和右值

左值是可以位于赋值语句的左侧,右值不能。
取地址符作用于左值运算对象,返回指向该对象的指针,这个指针是右值。
decltype作用于表达式,若表达式求职结果是左值,则返回引用。因为解引用运算符生成左值,所以decktype(p)的结果是int &。因为取地址运算符生成右值,所以decltype(&p)返回 int**即指向整形指针的指针。

13 sizeof

sizeof运算符返回一条表达式或一个类型名字所占的字节数。
sizeof*p 和 sizeof(p)等价,因为sizeof满足右结合律并且和 *优先级等价。其次sizeof不会求运算对象的值,即使空指针也没有影响。

14 无符号类型运算对象

若一个运算对象是无符号,另一个是有符号。①无符号类型大于带符号类型,则带符号类型转化为无符号类型。②带符号类型大于无符号类型,转换结果依赖机器:若无符号类型所有值都能存在该带符号类型中,则无符号对象转换成带符号对象。否则,带符号对象转换为无符号对象。(若能存在,则小的转化为大的)。

15 显示转换

①static_cast:只要不包括底层const,都能用其转换。double p1 = static_cast<double>(p)将p转换为double类型。void* p = &d;double *dp = static_cast<double*> p将从void转换为double
②const_cast:只能改变运算对象的底层const。cosnt char *pc;char *p = const_cast<char*>(pc)

16 函数声明

函数只能定义一次,但可以声明多次。
函数三要素:返回类型-函数名-形参类型

17 const形参

顶层const作用于对象本身。const int ci = 2;int i = ci;int * const p = &i;*p=0。其中p为指针常量,是顶层const,不能修改p的值,但是可以修改p所指对象的值.
当实参初始化形参时会忽略掉顶层const.

18 数组形参

①不允许拷贝数组②使用数组时会将其转换成指针.

数组引用形参:void print(int (&arr)[10]){};此处arr是具有10个整形的整形数组的引用.而f(int &arr[10])是将arr声明成了引用的数组.

19 initializer_list

①函数实参数量未知但所有实参类型相同,可使用.②实参不同,需要编写可变参数模板.
initializer_list对象中元素永远是常量值.
void f(initializer_list<int> list);调用:f({1,2,3});

20 引用返回的是左值,左值可以重新赋值

21 返回数组指针

函数可以返回数组的指针或引用.

21.1 使用类型别名

typedef int arr[10];//arr是类型别名,表示含10个整形的数组
using arr = int[10] //同上
arr* f(int i); //返回一个 指向含有10个整数的数组的指针
typedef int arr[10];
using arr = int[10];
arr & f(int i); //返回10个整数的数组的引用

21.2 声明返回数组指针的函数

int arr[10]; //arr含有10个整数的数组
int *p1[10]; //p1含有10个整形指针的数组
int (*p)[10] = &arr; //p是一个指向10个整形数组的指针.
type (*function(parameter))[dimension]
type:元素类型
dimension:数组大小
int (*func(int i))[10];
//待补充 p
int (&f(int i))[10]

21.3 使用尾置返回类型

auto f(int i) -> int(*)[10]; //f返回的是一个指针,该指针指向含有10个整形的数组.
auto f(int i) -> int (&)[10] //f返回10个元素的数组的引用

21.4 使用decltype

int odd[] = {1,2,3};
int even[] = {5,6,7};
decltype(odd) *arr(int i){
	return i ? &odd : &even;
}
decltype不负责把数组类型转换成对应指针,所以decltype结果是数组,因此想要表示arr返回指针还必须在函数声明附件一个*符号;
//此处返回数组的指针
int odd[] = {1,2,3};
int even[] = {5,6,7};
decltype(odd) &arr(int i){
	return i ? odd : even;
}
//返回数组的引用

22 重载和const形参

①顶层const不影响传入函数的对象,但是顶层const的形参无法和一个没有顶层const的形参区分开.

void f(int);
void f(const int); //重复声明
void f1(int*);
void f1(int *const); //重复声明.此时参数是指针常量.

②形参是某种类型的指针或引用,可通过区分指向的是常量还是非常量实现重载,此时的const是底层的.

void w(int &);
void w(const int&); // 新函数,作用于常量引用
void w1(int *);
void w1(const int*)//新函数,作用于指向常量的指针.此时参数是常量指针.

上面四个w,w1函数,因为const不能转化为其他类型,因此只能把const对象(或指向const的指针)传递给const形参.相反,非常量可转换为const,因此上面四个函数都能调用.但编译器会优先选用非常量版本.

23 const_cast和重载

const_cast可以将顶层const去掉.可以在重载函数的函数中间将const转化为非const. p209.

24 重载与作用域 p210

在函数外层定义过某个函数,在函数内再次声明这个函数,外层函数将被隐藏.
c++中名字查找,发生在类型检查之前.

string read();
void print(const string&);
void print(double);
void foo(int val){
	bool read = false;//新作用域,正确,外层read()被隐藏.
	string s = read(); //错误,外层read(),已经隐藏,现在read是bool值
	void print(int); //新作用域,外层两个p()都被隐藏
	print("asf"); //错误,print(const&) 被隐藏.
	print(val); //正确,调用print(int)
}

25 默认参数 p212

一旦某个形参被赋值了默认值,后面所有形参必须有默认值。
在调用过程,只能省略尾部的实参.f(,,1)(错误,只能省略尾部实参).f(1,,,)(正确,第二三个参数使用默认值
局部变量不能作为默认实参。

26 内联函数和constexpr函数 p214

调用函数比求等价表达式的值要慢一些.因为要经过①保存寄存器②返回时恢复③拷贝参数④程序转向新位置进行。
,内联函数可避免函数调用的开销.在函数的返回类型之前加上关键字inline,将其声明为内联函数。

constexpr函数

constexpr函数用于常量表达式的函数.定义其要遵守约定①函数返回类型及所有形参都得是字面值类型②函数体只能有一条return语句。

constexpr int f() {return 1};
constexpr int foo = f(); //正确,foo是常量表达式

constexpr函数被隐式指定为内联函数.也允许constexpr函数返回值并非常量.
constexpr int scale(int cnt) {return f() * cnt};此时当scale的参数是常量表达式的话,则他返回值也是常量表达式,反之不是常量表达式.int i=2;int a[scale(i)];(错误,scale(i)不是常量表达式)

27 assert预处理宏 p215

它使用一个表达式作为它的条件,assert(expr),若表达式为假,assert输出信息并终止程序执行,否则什么也不做
和预处理变量一样,宏的名字在程序内必须唯一。

28 函数匹配

①先看形参数量②看类型

29 函数指针 p221

函数指针指向的是函数而非对象.函数的类型由其返回值和形参类型共同决定,与函数名无关。
声明一个指向函数的指针只需要用指针替换函数名即可。

bool (*pf)(const string &,const string &);
//pf指向一个函数,该函数两个参数,都是const string的引用,返回值为bool类型。
// *pf两端括号必须有
bool *pf(const string&,const string &);//此时声明的是一个pf函数,参数是const string的引用,返回bool*。

29.1 使用函数指针 p222

bool com(const string&const string&);
pf = com; //此时pf指向com函数。
//调用
bool b1 = pf("hell","hell");
bool b2 = (*pf)("he","aw") //同理
bool b3 = com("gas","gsf") //同理

在指向不同函数类型的指针之间不存在转换规则。

int sumL(const string&const string&);
pf = 0; //正确,pf不指向任何函数
pf = sumL; //错误 返回类型不匹配

29.2 重载函数的指针 p222

void f(int*);
void f(unsigned int);
void (*pf)(unsigned int) = f; //pf指向f(unsigned)

void (*pf)(int) = f; //错误,形参列表不匹配
double (*pf)(int*) = f;// 错误,返回类型不匹配

29.3 函数指针形参 p222

void use(const string& s1,bool pf(const string& ,const string&))
void use(const string& s1,bool (*pf)(const string& ,const string&)) //等价
//调用
use("as",com) //会自动转换成指针。
typedef bool func(const string&,const string&);
typedef decltype(com) func1; // func和func1都是函数,decltype不返回指针,需要在结果前面加上*才能返回指针。

typedef bool (*func2)(const string&,const string&);
typedef decltype(com) *func3; // func2和func3是指向函数的指针

29.4 返回指向函数的指针 p223

using f = int(int*,int);	//f是函数
using ff = int(*)(int*,int); //ff是指针类型 指向函数

ff f1(int); //正确,pf是指向函数的指针,f1返回指向函数的指针
f f1(int); //错误,f1不一定返回函数
f *f1(int); //正确,显示指定返回类型是指向函数的指针
//直接声明f1
int (*f1(int))(int*,int); 
//①f1是函数->fi前面是*,所以f1函数返回一个指针->该指针有形参列表,所以该指针指向一个函数。
//使用尾置类型
auto f1(int) -> int (*)(int*,int)
//使用decltype
int sums(const string&);
int larg(const string&);
decltype(sums) *getFun(const string&); //getFun返回指向sums或larg的指针

c++primer前6章笔记

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值