C++Primer 第Ⅰ部分读书笔记

变量与基本类型

extern的使用

声明而不定义

extern int i;//声明而未定义
int j;//声明并定义

在全部文件中使用const量

extern const int size = 0;

指针和const

const int * p1 = &i;//指向常量的指针
int*const p2 = &i;//指向i的常量指针
const int *const p3 = &i;//指向常量的常量指针

constexpr (C++11)

constexpr int j = 0;//显式告诉编译器这是个常量
constexpr int * p4 = &i;//指向i的常量指针

类型别名

typedef

typedef double wages;

using (C++11)

using wages = double;

别名与指针引起的误会

typedef int* wages;//类型别名声明
const wages p1 = 0;//常量指针,而非指向const的指针

decltype类型 (C++11)

decltype的基本使用

int a = 0,*b=&a,&c=a;
decltype(a) x;//返回int类型
decltype(b) y;//返回int指针类型
decltype(c) z;//错误,返回引用类型必须初始化

decltype和引用

int a = 0,*b=&a;
decltype(*b) c;//错误,*b返回类型为引用
decltype((a)) d;//返回引用int类型,但未初始化,错误
int a = 0,*b=&a,&c=a;
decltype(a) x;//返回int类型
decltype(b) y;//返回int指针类型
decltype(c) z;//错误,返回引用类型必须初始化

头文件保护符

#ifndef STRING_H//判断是否定义变量,若定义返回真,执行直到遇到  #endif
#define STRING_H //把一个名字设定为预处理变量


//源代码



#endif

类型转换

显式强制转换

基本格式:

cast-name<type>(expression);

static_cast

内层不包括const,即可使用 static_cast

找回void*指针的值

void*p1 = &d;
double *p2 = static_cast<double*>(p);

const_cast

只能改变底层const的类型转换,去掉const性质

const int val = 21;//赋值
const int*p1 = &val;//p1指向val
int*p2 = const_cast<int*>(p1);//强制类型转换
*p2 = 7;//改变值,但该行为是未定义的

不能通过p2改变val的值,该行为是未定义的

那么const_cast的作用是什么? 一个函数如果需要非常量作为参数,并且我们明确函数不会修改该值,那么我们可以通过类型转换传递参数达到目的

const_cast从来不是为了修改常量而设计的

reinterpret_cast

这里不细讲,待补充

旧式类型强制转换

typename(expr);//函数形式的强制转换
(typename)expr;//C语言风格的强制转换

函数

含有种类可变形参的函数

void fun(initializer_list<int>num);

initiallizer_list可提供多种与容器相同的方法

比如begin(),size(),size()

这样便可以传递多个形参

主函数main()的返回值

为了返回值不随机器改变而改变,应该使用cstdlib头文件中的两个预处理变量

#include<cstdlib>
int main()
{
      if(some_faliure)
            return EXIT_FAILURE;
      else
            return EXIT_SUCCESS;
}

返回数组指针

int (*fun(int val) ) [10];  //表示返回一个指向十个元素的数组的指针

使用尾置返回类型

auto fun(int i ) -> int(*)[10];

*必须用括号括上,原因如下

int *p1[10];// 表示一个含有十个指针的数组
int(*p)[10];//表示一个指向十个元素数组的指针

using

using Arrt = int [10];
Arrt fun(int i );

constexpr函数 (C++11)

constexpr fun(){return 42;)
constexpr int i = fun();

使用constexpr函数需要遵循返回类型为字面值类型,并且函数内只能有一句return语句

除此之外,constexpr函数返回的不一定是常量,当形参为常量表达式时,函数返回常量

否则,返回非常量

调试帮助

assert预处理宏

assert定义再 cassert头文件中

assert(exp);

若exp为真,则继续执行,若exp为假,则终止程序进行

NDEBUG预处理变量

#define NDEBUG

若定义了NDEBUG,则assert什么也不做

_
func

定义存放函数

FILE

定义存放文件

LINE

定义行数

TIME

定义编译时间

DATE
_定义编译日期

函数指针

函数指针的基本使用

bool fun(int i);
bool (*p)(int i );
p = fun;
p = &fun; //两种方式等价
int i = p(4);
int j = (*p)(4);//两种方式等价

与普通指针类似,函数指针需要声明并且不能指向不同类型

返回指向函数的指针

int (*p(int i) ) (int i);
using p = int (*q) (int i );
p fun(int i );

默认构造函数 =defalut (C++11)

class MAP
{
      MAP() =default;//若类中有别的构造函数,但没有默认构造函数,则需要自己提供一个
}

委托构造函数 (C++11)

class Data
{
public:
           Data(int Val,int Key) : val(Val),key(Key)  {}
           Data(int Val): Data(Val,0)   {}
}

explicit构造函数

class Data{
public:
           explicit Data(int Val):val(Val) {}  //只能用于直接初始化,并且不能隐式转换

聚合类

1.所有成员为pubilc

2.没有类内初始值

3.没有构造函数

4.没有基类也没有虚方法

struct  Data
{
    string s;
    int val;
}

Data temp = {"s",2);//可直接花括号初始化

静态成员

在类中声明静态成员,在类外定义并初始化静态成员

与函数类似,值得注意的是,如果是数据类型,也必须给予类型

class MAP
{
    static int a;
}

int a = 5;

也可以这样初始化

class MAP
{
     static constexpr int a = 5;
}

静态成员可以用来声明不完全类型

class MAP
{
public:
     //...
priviate:
    static MAP a;//但不能直接声明
    MAP* b;