>>>>
学习C++一年多了,再次看C++primer,发现还是有很多基础知识不知道,因此开始整理这些,有不对的地方望大家指出。
>>>>
一、变量和基本类型
/*
关于初始化问题:
定义在函数体外的变量未被初始化时,则初始化为0;
在函数体内的则不指定具体的值。
*/
int global_int;//0
int main(){
int local_int;//不确定的值
}
/*
void* 是一种特殊的指针类型,可用于存放任意对象的地址;对其操作有限,只能和别的指针做比较、
作为函数的输入,输出,或者赋值给另外的一个void*指针。
*/
/*
与const相关
*/
const int i = get_size();//在运行时初始化
const int j = 42;//在编译时初始化
double dval = 3.14;
//中间隐式的类型转换,const int temp = dval
//const int &v = temp;
const int &v = dval;
/*
decltype类型指示符
decltype的表达式如果加上了括号的变量,结果将是引用
*/
decltype((i)) d;//error,引用必须初始化
decltype(i) e;
/*
头文件不应该包含using声明,当该头文件被引用到其他文件中是,会因为命名空间的问题出现不可预料的结果
*/
二、字符串、向量和数组
#==================================string=============================================#
/*
string 类型的读取
*/
int main(){
string s;
cin >> s;
cout << s <<endl;//将自动忽略开始的空格,直到读取到下一个空格
return 0;
}
//使用getline可以获取整行,并且去掉换行符
int main(){
string line;
while(getline(cin,line))
cout << line <<endl;
return 0;
}
/*
cctype中包含的一些函数
*/
tolower(c); \\如果c是大写字母,则输出小写;否则不变
toupper(c);\\同理
string s("Hello world!!!");
//转换成大写
for(auto &c : s)//注意为引用
c = toupper(c);
cout << s << endl;
/*
string 与 C风格字符串转换
*/
string s("Hello world");
char * str = s;//error
char * str = s.c_str();
#==================================vector=============================================#
/*
创建指定数量的元素
*/
std::vector<int> v(10,-1);
std::vector<string> v(10,"hi");
std::vector<int> v(10);
/*
初始化列表与元素数量
*/
std::vector<char> v(10);//10个元素,初始化为null
std::vector<int> v{1,2};//2个y元素
#==================================iterator=============================================#
/*
尾后迭代器
*/
std::vector<int> v(10);
auto s = v.end();
int a[10] = {0};
auto a = &a[10];//int * a = &a[10];
auto s = end(a);//int * s = &a[10];end在iterator头文件中
/*
迭代器返回值根据对象的类型而定,常量则返回const_iterator,否则为iterator
*/
std::vector<int> v1;
const std::vector<int> v2;
auto v1 = v1.begin();
auto v2 = v2.begin();//const_iterator
/*
利用迭代器运算实现二分查找,必须有序
*/
bool binarySearch(std::vector<int> v,int obj){
auto ibegin = v.begin();
auto iend = v.end();
auto mid = ibegin + (iend - ibegin)/2;
while(mid != iend && *mid != obj){
if(*mid > obj)
ibegin = mid + 1;
else
iend = mid
mid = ibegin + (iend - ibegin)/2;
}
if (mid != iend)
{
return true;
}
return false;
}
#==================================数组和指针=============================================#
/*
使用数组作为一个auto变量的初始值时,其推断得到的类型为指针
*/
int ia[] = {1,2,3,4,5};
auto ia2(ia);//ia2为指针指向,ia的第一个元素
decltype(ia) ia3 = {1,2,3,4,5};//ia3为含有5个元素的数组
/*
标准库函数中的begin和end
*/
int ia[] = {1,2,3,4,5};
int *beg = begin(ia);//ia的首元素
std::vector<int> v(begin(ia),end(ia));
#==================================多维数组=============================================#
/*
采用auto打印二维数组
*/
int a[3][3] = {0};
for(const auto &row : a)
for(const auto col : row)
cout << col <<endl;
//一下为错误用法,auto row,会解析为int *,因此不允许在int *中遍历
for(auto row : a)
for(auto col : row)
cout << col << endl;
三、函数
1、函数的形参初始化的机理与变量初始化一样
2、数组形参
/*
数组具有两个特殊的性质:
1、不允许拷贝数组
2、使用数组时会将转换成指针
*/
//等价的三种方式
void print(const int *);
void print(const int[]);
void print(const int[10]);
//管理指针参数的三种方法
//1、数组本身含一个结束标志
void print(const char *cp){
if(cp)
while(*cp)
cout << *cp++;
}
//2、使用标准库规范
void print(const int *beg,const int *end){
while(beg != end)
cout << *beg++;
}
//3、显示传递一个数组长度
void print(const int a[],int size){
}
3、函数值是如何被返回的:返回一个值的方式和初始化一个变量或形参的方式完全一样;返回的值用于初始化调用点的一个临时变量
4、列表初始化返回值(C++11)
vector<string> process()
{
//
//...
//a和b为string对象
if(a == b)
return {};//返回一个空的vect对象
else if (a > b)
return {"hello","word"}; //返回vector初始化列表
else
return {"hello",a,b};
}
5、返回数组指针
/*
在不能返回数组的情况下,可以返回数组的指针或者引用
*/
typedef int arrT[10]; //arrT是一个类型的别名,表示含有10个整数的数组
using arrT = int[10];
arrT * func(int i); //返回一个指向含有10个整数的数组的指针
/*
例子:返回数组的引用
*/
string a[4] = {"abc"};
string b[4] = {"a","b"};
using arrT = string[4];
arrT &fun(int i){
if(i == 0)
return a;
else
return b;
}
6、constexpr函数:函数的返回值类型及所有的参数类型都得是字面量,而且函数体内必须有且有一条return语句。
7、NDEBUG预处理变量,可以使用在调试信息中
#define NDEBUG
void test()
{
cout<<__func__<<endl;
cout<<__LINE__<<endl;
cout<<__TIME__<<endl;
}
8、函数指针
//比较两个字符串的长度
int compareString(const string &,const string &);
//定义函数指针
int (*pf)(const string &,const string &);
//初始化
pf = compareString;//等价于 pf = &compareString;
//调用,以下2个等价
bool b1 = pf("a","b");
bool b2 = (*pf)("a","b");
//函数指针做参数
//显示与隐式,将会自动转换
void useBigger(const string &a,const string &b,bool pf(const string &,const string &));
void useBigger(const string &a,const string &b,bool (*pf)(const string &,const string &))
9、返回指向函数的指针
//返回类型与参数不一样,不能自动转换
using F = int(int *,int); //F是函数类型
using PF = int(*)(int *,int); //PF是指针类型
PF f1(int);
F * f2(int);
int (*f3(int))(int *,int);
auto f4(int) -> int(*)(int *,int);//以上四个都是返回函数指针类型
//例子
using fp = int (int,int);
int add(int a,int b){
return a+b;
}
int dev(int a,int b){
return a-b;
}
int main()
{
vector<fp *> vpf;
vpf.push_back(add);
vpf.push_back(dev);
for(vector<fp *>::iterator it = vpf.begin();it != vpf.end(); it++)
cout<<(*it)(3,2)<<endl;//注意
return 0;
}
github:https://github.com/DlmuZQ/cpplearnagain/tree/master/CppLearnAgain
摘自《C++Primer》