- 下面的第5行代码可以写成第6行注释的代码
#include<iostream> int main() { int v1{}, v2{}; (std::cin >> v1) >> v2; //std::cin>>v1>>v2; (std::cout << v1) << " " << v2 << std::endl; return 0; }
- char类型在有些机器上是有符号的,在有些机器上是无符号的,需要使用char类型,最好明确是signed char还是unsigned char.
- 当赋给无符号类型一个超出其表示范围的值是,得到的结果是初始值对无符号类型表示数值总数取模后的余数,但是赋给有符号类型一个超出其表示范围的值,结果是未定义未知的,程序可能继续工作,可能崩溃,也可能产生垃圾数据。如果一个表达式中包含有符号和无符号类型,则有符号类型会转换成无符号类型进行计算,切勿混用带符号和无符号类型进行计算。
#include<iostream> #include <climits> int main() { unsigned u = 10, v = 42; int i = -42; long long l = i + 10, num = UINT32_MAX + 1LL, g = i * 10; std::cout << u - v << " " << u + i << " " << u * i << std::endl; std::cout << (l + num) % num << " " << (g + num) % num << std::endl; return 0; }
4294967264 4294967264 4294966876 4294967264 4294966876
- 使用泛化的转义序列,其形式是\x后紧跟着1ge或者多个16进制数字,或者\后紧跟着1个或者多个八进制数组其中数字部分表示的是字符对应的数值,如果\后面跟着的八进制数组超过3个,则只有前面三个数字与\构成转义序列,如果\x跟着的十六进制数超过4个,则只有前面4个数组与\构成转义序列。
#include<iostream> #include <climits> int main() { int num = ' '; std::cout << std::hex; std::cout << num << std::endl; std::cout << '\x20' << '\12' << "234" << std::endl; return 0; }
20 234
- void可以存放任意对象的地址,包括另一个指针所指向的地址,但是void的作用比较有限,只能拿它和别的指针比较,作为函数输入输出,或者给另外一个void指针赋值,但是不能直接操作void类型的指针所指向的对象。除了void*是个例外,其他大部分情况下指针的类型和指向的对象类型要严格匹配,不发生隐式类型转换。
#include<iostream> #include <climits> int main() { double num = 3.14, * pd = # void* pv = # pv = pd; std::cout << *pd << " " << *(double*)(pv) << std::endl; }
- 引用本身不是一个对象,所以不能定义一个指向引用的指针,但是指针是对象,所以可以存在对指针的引用。
#include<iostream> #include <climits> int main() { int i = 42; int* p; int*& r = p; r = &i; *r = 1; std::cout << i << " " << *p << " " << *r << std::endl; }
- const修饰的对象仅在定义文件内有效,非定义文件不存在该对象,如果想在其他文件一并使用,则对const变量不管是声明还是定义都加上extern关键字,这样只需要定义一次就够了,常变量引用初始化的时候可以使用任意表达式作为初始值。如果const引用的不是一个const的对象,则该对象可以通过另一个非const引用改变值,也可以通过自身改变值,但是不能通过const引用改变值
//file.cc文件定义并初始化一个常变量,该常变量能够被其他文件使用 extern const int bufSize=fuc(); //file.h头文件 extern const int bufSize;//和file.cc文件定义的bufSize是同一个 double dval=3.45; int a=43,b=34; //允许任意表达式作为初始值 const int &ri=a+b; //允许由双精度浮点数生成一个临时的整形变量 const int &rp=dval; //允许常变量引用初始化值是常量 const int& int_ptr = 10;
#include<iostream> #include <climits> int main() { int i = 42; int& r1 = i; const int& r2 = i; std::cout << r1 << " " << r2 << " " << i << std::endl; r1 = 1; std::cout << r1 << " " << r2 << " " << i << std::endl; i = 2; std::cout << r1 << " " << r2 << " " << i << std::endl; }
42 42 42 1 1 1 2 2 2
- constexpr可以类型必须用常量表达式初始化,一个constexpr指针的初始值必须是nullptr或者0,或者储存于某个固定地址的对象(比如函数体外)
#include<iostream> #include <climits> //x必须定义在函数体外才能被consrexpr修饰 int x = 10; int main() { const int a = 10; constexpr int b = 20; constexpr int c = a + b; //p1是指向整形常量的指针, const int* p1 = nullptr; //p2是指向整形的常量指针 constexpr int* p2 = 0; //p3是指向整形常量的常量指针 constexpr const int* p3 = &x; //p4是指向整形的常量指针 constexpr int* p4 = &x; p1 = &b; *p4 = 20; std::cout << *p1 << " " << p2 << " " << *p3 << " " << *p4 << std::endl;
}
-
CPP允许给类型起别名,包括使用typedef和using,注给指针起别名的时候使用const修饰的指针是常量指针,而不是指向常量的指针。
#include<iostream> #include <climits> int main() { typedef double wages; typedef wages base, * p; base i = 1.0; const p ptr = &i; //相当于double * const ptr = &i; *ptr = 20; std::cout << i << " " << *ptr << std::endl; double* const num = &i; *num = 30; using Son = int; Son s = 10; }
-
auto一般会忽略掉顶层的const,不能将类型变成指向数据的常量指针,但是能够变为指向常量的指针,如果希望变出来的数据能够是指向数据的常量指针,则可以在auto左边加上const
#include<iostream> #include <climits> #include<typeinfo> int main() { int i = 10; const int ci = i, & cr = ci; auto a = i; auto b = ci; auto c = cr; auto d = &i; auto e = &ci; const auto f = ci; auto& g = ci; const auto& j = 42; auto& m = ci, * p = &ci; const auto* x = &ci; std::cout << "a " << typeid(a).name() << std::endl; std::cout << "b " << typeid(b).name() << std::endl; std::cout << "c " << typeid(c).name() << std::endl; std::cout << "d " << typeid(d).name() << std::endl; std::cout << "e " << typeid(e).name() << std::endl; std::cout << "f " << typeid(f).name() << std::endl; std::cout << "g " << typeid(g).name() << std::endl; std::cout << "j " << typeid(j).name() << std::endl; std::cout << "m " << typeid(m).name() << std::endl; std::cout << "p " << typeid(p).name() << std::endl; std::cout << "x " << typeid(x).name() << std::endl; } ``` ```cpp a int b int c int d int * __ptr64 e int const * __ptr64 f int g int j int m int p int const * __ptr64 x int const * __ptr64
-
decltype注意点:
#include<iostream> #include <climits> #include<typeinfo> int main() { int i = 42, * p = &i, & r = i; decltype(r + 0) b;//表达式加法结果为int类型,b为未初始化的int decltype(*p) c=i; //如果表达式的内容是解引用操作则为引用类型,c为int&类型 decltype(r) d = i;//r本身是一个引用类型,所以d为引用类型 decltype((i)) e = i;//变量名加上括号是引用类型,所以e是引用类型 decltype((i + i)) f;//表达式加上括号不是引用类型 const int* const num = &i; decltype(num) ret = &i;//ret属于指向常量的常量指针 int z = 100; //*ret = 10; //ret = z; }
-
如果一个表达式中已经有了std::string的size()函数,就不要使用有符号整形,因为size()有可能返回一个unsigned int类型的数据。
-
string的加号+必须保证+号的两侧至少有一个是string
#include<iostream> #include <climits> #include<typeinfo> int main() { std::string s1 = "123"; std::string s2 = "123" + s1 + "sdf"; std::string s3 = s1 + "123" + s2; std::string s4 = (s1 + "sdf") + "sdf"; }
-
vector初始化注意一下代码:
#include <iostream> #include <climits> #include <vector> int main() { std::vector<int> svec; std::vector<int> svec1(svec); std::vector<int> svec2 = svec; std::vector<std::string> svec3{ "wer","sdf","Sdf" }; //std::vector<std::string> svec4("wer", "sdf", "Sdf"); std::vector<std::string> svec4(10, "wer");//创建10个wer std::vector<int> svec5(10);//创建10个值为0的int类型 std::vector<int> svec6{ 10 };//创建一个值为10的int类型 std::vector<int> svec7(10, 1);//创建10个值为1的int类型 std::vector<int> svec8{ 10,1 };//创建一个为10和一个为1的int类型 std::cout << svec6.front() << std::endl; }
-
范围for语句for(statement : expression)体内不允许改变其遍历序列
-
迭代器中iterator可读写相关对象的元素,const_iterator只可以读取,不可以写相关元素。
#include <iostream> #include <climits> #include <vector> int main() { std::vector<int> vec{ 1,4,2,4,6,23 }; std::vector<int>::iterator it1 = vec.begin() + 2; *it1 = 100; for (auto x : vec) { std::cout << x << " "; } std::cout << std::endl; std::vector<int>::const_iterator it2 = vec.begin() + 2; //*it=10; std::cout << *it1 << " " << *it2 << std::endl; }
-
begin和end迭代器返回的具体类型由对象是否是常量决定,如果是常量,begin和end返回const_iterator,如果不是常量返回iterator,而cbegin和cend不管是否是常量容器都会返回const_iterator类型