写sort的时候可以用lambda表达式
1
sort(vi.begin(),vi.end(),[](const int elem1, const int elem2)->bool{return elem1<elem2;});
stl中的set有set_intersection,set_union,set_difference的功能,使用方法如
1
set_difference(a.begin(),a.end(),b.begin(),b.end(),inserter(c,c.begin()));
unique_copy是unique相似用法
1
unique_copy(ss.begin(),ss.end(),back_inserter(s));
extern int i代表要到别的文件中找i
vector<int>::const_iterator it1;//这玩意是不能改指向的数据 const vector<int>::iterator it2;//这玩意是自己不能改,没啥用
然后fin就可以当作一般的cin差不多用法了。 同时,这里定义的fin和cin都属于istream,其它也属于istream的还有stringstream,用法如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
* const的含义是不能修改,可能是不能被修改的变量;constexpr的含义是真正的常量(比如固定的数字),可以直接在编译期处理出来
* 加::可以在局部调用全局变量,即使局部有同名变量
* const int *p或者int const *p表示p指向的位置是个常量,但p不是;int *const p即可。若需要两者皆为常量,则int const *const p
* nullptr代表空指针,但c中是NULL或0
* 文件输入输出流fstream包含ifstream和ofstream,定义时
```c++
ifstream fin{"a.txt"};//或者下面这样
ifstream fin;fin.open("a.txt");//注意程序结束前要close
fin.close();1
2
3
4string s;
stringstream strin(s);
int n;
strin>>n;cin>>当中右移符号的返回值为左端的istream&对象,因此在cin>>x>>y中,cin>>x执行完返回一个cin,继续读cin>>y。判断语句中cin会被强转为bool型。当cin.eof()为true的时候条件判断中的cin是false
1
2
3while (cin>>n) {/*what you want to do here*/}
while (getline(cin,s)) {/*...*/}//返回值实际上也是个istream&,和上面这句的返回值类型相同
while (!cin.eof()) {cin>>n;/*...*/}//这里不加点东西就会渲染失败
void f(char); void g(char &); void h(const char&); char c='A';int d=97; f('a');//right f(49);//right f(c);//right f(d);//right g('a');//wrong you can't refer a constant g(49);//wrong g(c);//right g(d);//wrong you can't refer a different variable type h('a');//right the compiler would introduce a temporary variable h(49);//right the compiler would introduce a temporary variable h(c);//right h(d);//right the compiler would introduce a temporary variable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24//这里不加点东西就会渲染失败
* ```c++
namespace My
{
int a;
void f(){a++};
}
namespace AA
{
using namespace My;//直接把两个杂糅起来
}
namespace AA
{
int b;//这样算作添加
}
int main()
{
using namespace My;//1 introduce all,更接近于全局和局部的关系
using My::f;//2 introduce My::f
using My::a;//3 introduce My::a,只引入了一个局部标识符,和下面a同级
int a;//4 与上面这行会矛盾,但与1不矛盾
cout<<a<<My::a<<endl;
}for static global names, use unnamed namespace to avoid their use in other source files.
如果是全局变量,就会在所有文件内生效,就乱套啦
1
2
3
4
5
6
7
8namespace//effective in the whole source file
{
int a;
}
void f()
{
a=1;
}ADL技术,又称koenig查找,会根据参数所在的命名空间找调用的函数
namespace s=std;//重命名
1
2
3
4
5
6
7
8
9
10
11
12
* ODR技术 单一命名规则:不在同一个翻译空间内的两个一模一样的东西(名称和内部变量名等一切会被编译的东西),会被认为是同一个东西,不会报错。(但是它有啥用?)
* C++默认会把函数名改成包含参数和返回值信息的样子,来内部区分
* ```c++
int &use_count()//alternative to use global variables
{
static int uc=initval;
return uc
}
void f(){use_count()++;}try catch throw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20int f(int a,int b)
{
if (b==0) throw div0(1);
if (a==0) throw div0(2);
if (b==0x3f3f3f3f) throw aaa;//if no catch matches it, the program will terminate
return a/b+b/a;
}
int main()
{
int n=1,m=0;
try:
{
f(n,m);
}
catch(div0 x)
{
cout<<"div0"<<x<<endl;
}
//catch(...) to catch all other types
}
默认的class赋值是bitwise,但是如果里面有指针可能会出锅(从其中一个把它delete之后另一边就gg)
class A{ int d; public: int getd() const; int getd(); //构成重载,会自动适配 //重载就是同一个变量名不同函数 } int A::getd() const{return d;} int A::getd(){return d++;}
//这里不加点东西就会渲染失败1
2
3
4
5
6
7
8
9
10
11//这里不加点东西就会渲染失败
* ```c++
class A
{
private:
int x,y;
public:
A& operator+(const &A);//A后面的&表示返回一个引用,可以修改。否则返回的是const的局部变量
//返回值记得设return *this;
}class A { void operator==(const &A)=delete//禁止使用默认的==运算符 void operator&(const &A)=delete//禁止使用默认的取地址运算符 }
1
2
3
4
5
6
7
8
9
10
11//这里不加点东西就会渲染失败
* ```c++
class complex
{
public:
complex& operator+(const int &b);
};
complex a;
int main(){2+a//wrong 只定义了a+2,没定义2+a
//但是可以在class里面写个complex(const int &b) {x=b;}然后它就会自动转类型了由于ADL,namespace当中会自动寻找操作数相同的重定义运算符来用。重载前后操作数相同,不能变化结合性
operator.和operator->的左边的东西不会被隐式转换
字面量操作符literal,可以实现1+2.0i这样的表示,方法就是
1
complex operator""_i(long double x){return {0,x};}//必须放在class外
其中long double是因为double不合法…这些是合法类型
1
2
3
4
5
6
7char const*
unsigned long long
long double
char const*, std::size_t
wchar_t const*, std::size_t
char16_t const*, std::size_t
char32_t const*, std::size_t老师ppt给的例子的字面量操作符没有下划线,但是貌似用户自定义的建议以下划线开头,因为以后的c++版本可能会用到不带下划线的。只会报warning
假设需要把当前class转化为已有类型T,那么在class里面写operator T(const T &x)const{return xxxx;}
在某些式子里可能调用转换函数或者构造函数进行类型转换 为了避免ambiguity 使用显示转换
隐式转换最多帮你转一级,因为更多就会产生歧义
隐式转换时候必须保证唯一性,比如有个f(x)一个f(y),同时x和y都可以由int构造成,那么f(1)就gg
Exact match
Match using promotions
Match using standard conversions
Match using user-defined conversions
Mismatch, function undeclared
friend的声明位置无所谓private public
一个class的friend可以是另一个class的member function/一个class可以是另一个class的friend class
friend只是标明了这玩意存在,而没有真正定义它
friend class可以是前面定义过的class,也可以是后面定义、但在当前enclosing scope中定义的class
friend function可以是类似friend class的地方定义的,也可以是参数所在enclosing scope中定义的
关于右值引用和拷贝构造 看这里
构造函数前加explicit就可以让这个构造函数只能被显式调用
为了区分是a++还是++a,定义的时候后缀多一个标记用的参数int。a++相当于a.operator++(0)
vtbl (v table)虚函数表 vptr虚函数表指针
析构通常都是虚函数
virtual void f()=0; 有纯虚函数的就是抽象类
class D:public A,private B,protected C{ //多重继承时要避免两边有一样的东西 二义性 //继承来继承去可能会生成一个DAG }
1
2
3
4
5
6
7
8
9
10
11
12
13
* string\<T\>里面的返回值只要写string,到了外面就得string\<T\>
* 模板的实例化 第一次用到它时候就会把这个类型代进去,过程叫Template instantiation,结果叫specialization。成员函数用到了才会实例化。定义某个指针时候没必要马上把它指向的类型实例化
* ```c++
template<typename T,int i,typename compare=std::less<T>>//std::less<T>是默认参数,如果没有就编译错误 compare如果要传入的话 就是传入一个返回值为bool的函数
class A
{
T a[i];
bool f(T x,T y){return compare(x,y);}
}
//i需要是编译期能搞定的值更特殊的模板会优先选择(我能推出你 你不能推出我) ambiguous会CE
完全特例化complete specialization
1
template<> class Vector<void*>{}
部分特例化partial specialization
1
template<typename T> class Vector<T*>:private Vector<void*>{}
RAII: Resource Acquisition Is Initialization 已构造的对象最终会销毁,即它的析构函数最终会被调用。函数在正常结束或者throw退出时候都会把局部的东西清掉
#include <exception> //standard exception 标准库异常