using
声明#include
using std::cin;
using std::cout; using std::endl;
string
string s1; //默认初始化,s1是一个空字符串
string s2(s1);
string s2 = s1;
string s3 = "value";
string s3("value");
string s4(n, 'c');
string
string s;
cin >> s; //自动忽略开头的空白(空格、换行符、制表符等),直到遇到下一处空白为止
getline(cin. line); //每次读取一行,直到遇到换行符。最后换行符被丢弃
line.empty();
auto len = line.size(); //len是类型 `string::size_type`。 unsigned
// 如果一条表达式中已经有了size()函数,就不要再使用int了。
// 自动转换是int-->unsigned int
stirng
相加:字符串字面值并不是string对象string s4 =s1 +", ";
string s5 = "hello " + ", "; //错误: + 的两个运算对象至少一个是string对象
范围for
循环#include
using std::string;
string s("hello");
decltype(s.size()) punct_cnt = 0; //类型声明
for(auto c : s) //若要改变则 auto &c : s 。c的类型是 char
if(ispunct(c)) //
++punct_cnt;
下标运算符[]
:接收的参数类型是string::size_type
。无符号类型的。c++
标准库并不要求检测下标的合法性
vevtor
:类模板,为编译器生成类而编写的一份说明
#include
using std::vector
vector<int> ivec; //<对象> <>里不能是引用,因为引用不是对象
vector
vector v1; //空vector
vector v2(v1);
vector v2 = v1;
vector v3(n, val);
vector v4(n); //n个对象,值是默认值
vector v5{a, b, c};
vector v5 = {a, b, c};
vector<string> v6("hi"); //error : {}
vector<string> v7{10}; //等价于 v7(10). 类型不匹配的情况
vector<string> v8{10, "hi"}; //等价于 v8(10, "hi")
实例化:编译器根据模板创建类或函数的过程
vector
操作
vector<int> v1;
v1.push_back(1); //添加元素。 如果出现该语句,则不能使用范围for循环
auto b = v.begin(), e = v.end(); //如果为空,则都是尾后迭代器
for(auto it = s.begin(); it != s.end(); ++it)
//!= 标准容器看迭代器都有的定义, ++it比 it++更高效
vector<int>::iterator it;
string::iterator it2;
vector<int>::const_iterator it3;
string::const_iterator it4;
vector<int> v;
const vector<int> cv;
auto it1 = v.begin(); //vector::iterator ,由对象是否是常量决定
auto it2 = cv.begin(); //vector::const_iterator
auto it3 = v.cbegin(); //vector::const_iterator
it->mem;
(*it).mem;
凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素
constexpr
和常量表达式:值不会改变,在编译过程就得到计算结果的表达式。字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式
const int max_files = 20;
const int limit = max_files + 1;
int staff_size = 27; //不是常量表达式
const int sz = get_size(); //看函数是不是constexpr函数
constexpr int mf =20;
int arr[10]; //[]内是常量表达式
int a2[] = {0, 1, 2}; //大小是3
int a3[5] = {0, 1, 2}; //后面2个元素初始化为0
char a1[] = {'c', 'd'}; //大小是2
char a2[] = {'c', 'd', '\0';} //含有显示的空字符
char a3[] = "c++"; //大小是4,自动添加空字符
const char a4[6] = "daniel"; //error: 大小是7,没有空间存放空字符
int *ptrs[10]; //ptrs是含有10个整型指针的数组。 类型修饰符从右向左依次绑定
int &refs[10]; //error : 不存在引用的数组。 引用不是对象
int (*parray)[10] = &arr; //parray是指针,指向含有10个整数的数组
int (&arrref)[10] = arr; //arrref是引用,引用含有10个整数的数组
int *(&arry)[10] = ptrs; //arry是引用,引用的是含有10个int指针的数组
num++
非法, num++
是一个指向数组开头的常量,不能作为左值。string nums[] = {"1", "2", "3"};
string *p = &nums[0]; //[]里面的索引值是有符号的
C风格字符串:是为了表达和使用字符串而形成的一种约定俗称的写法。按此习惯书写的字符串存放在字符数组中并以空字符(null)结束。
string
对象转换为C风格字符串
char *str = s.c_str(); //调用成员函数。
//如果想一直使用该字符串数组,组好重新拷贝一份
vector
对象int int_arr[] = {0, 1, 2, 3, 4, 5};
vector<int> ivec(begin(int_arr, end(int_arr))); //,返回的指针int*
int ia[3][4] = {{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};//3个元素,每个元素是4元素数组
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
int ia[3][4] = {{1}, {2}, {3}};
int (&row)[4] = ia[1]; //把row绑定到ia的第二个4元素数组上
for
size_t cnt = 0; //数组[]内的类型是size_t
for(auto &row:ia) //不能是 auto row:ia。这样返回的int[4]数组的指针,
//下面循环就不对了。 加上&,返回的是数组
for(auto &col:row){ //最后一个循环,可以去掉&
col = cnt;
}
int ia[3][4];
int (*p)[4] = ia; //名字-->指针
p = &ia[2];
int (&row)[4] = ia[1]; //把row绑定到ia的第二个4元素数组上
for(auto p=ia; p!=ia+3; ++p) //名字-->指针, p是指针,指向含有4个整数的数组
for(auto q=*p; q!=*p+4; ++q) //*p是数组,*P是数组名,名字-->指针
for(auto p=begin(ia); p!=end(ia);++p)
for(auto q=begin(*p); q!=end(*p); ++q)
using int_array = int[4];
typedef int int_array[4];