C++学习笔记

第2节

防卫式声明,防止重复include引起的问题(guard)

1
2
3
4
5
//complex.h
#ifndef _COMPLEX_
#def _COMPLEX_
...
#endif

第3节

inline 内联函数

构造函数

1
2
3
4
5
6
7
8
9
public:
complex(double r = 0,double i = 0)
:re(r),im(i)
//上面的默认值是推荐用法
{}
...
complex c1(2,1)
complex c2
complex* c3 = new complex(4)

第4节

数据是private

参数、返回值尽可能拿引用传递:除了返回值需要新创建对象的情况

能加const的函数尽量加const

1
type function () const { return result}

第6节

操作符重载

1
2
3
complex::operator += (const complex& r){
return
}
1
2
3
4
5
//ostream不加const 
ostream& operator << (ostream& os, const complex& x)
{
return os << '(' << real(x) << ',' << imag(x) << ')';
}

第7节

1
2
3
4
5
6
7
8
9
10
11
12
class String
{
public:
String(const char* cstr = 0);
String(const String& str);
String& operator =(const String& str);
~String()
char* get_c_str() const {return mdata};

private:
char* m_data;
}

拷贝构造(浅拷贝会内存溢出)

1
2
3
4
5
inline String::String(const String& str)
{
m_data = new char[ strlen(str.m_data) + 1];
strcpy(m_data,str.m_data);
}

拷贝赋值

1
2
3
4
5
6
7
8
9
10
inline String::operator = (const string& str)
{
//不使用这个自我赋值判断,会刹掉自己
if(this == &str)
retrun *this
delete[] m_data;
m_data = new char[ strlen(str.m_data) + 1];
strcpy(m_data,str.m_data)
return *this;
}

第8节

new :先分配内存,再调用ctor

delete:先调用析构函数,再释放内存

array new 要搭配 array delete使用

第15 16 17 18节

转换函数 ,构造方法也可以当转换函数转,比如4转为4/1

explicit :加在构造方法前面,表示必须得显示调用

1
2
3
4
5
6
7
8
9
10
11
class Fraction
{
public:
Fraction(int num,int den=1)
: m_numberator(m), m_denominato {}
operator double() const{
return (double)(a/b)
}
...
Fraction f(3,5)
double d=4+5
1
2
3
Fraction operator+(const Fraction& f){
return Fraction(...);
}

pointer like classes 智能指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<class T>
class shared_ptr
{
public:
T& operator*() const
{ return *px; }
T* operator->() const
{ return px; }

shared_ptr(T* P) :px(p){}
private:
T* px;
long* pn;
}

Function-like classes

1
2
3
4
5
template <class T>
struct identity{
const T&
operator()(const T& x) const {return x;}
}

第19 - 25节

namespace 可以代码放一个文件进行,然后用namespace分割

类模板、函数模板、成员模板,函数模板使用时无需指定类型

1
2
3
4
5
6
7
8
9
10
11
12
template <class T1,class T2>
struct pair{
T1 first;
T2 second;
pair():first(T1()),second(T2);
pair(const T1& a,const T2& b):
first(a),second(b){}

template <class U1,class U2>
pair(const pair<U1,U2>& p):
first(p.first),second(p.second){}
}

模板特化,可以理解为限定类的模板特殊设计

1
2
3
4
5
6
template <>
struct hash<char>{
size_t operator()(char x) const{
return x;
}
}

模板模板参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<typename T,
template <typename T>>
class Container
>
class XCLs{
private:
Container<T>c;
public:
...
}

template<typename T>
using Lst = list<T, allocator<T>>;

//XCLs<string, list> mylst1; 错的
XCLs<string,Lst> mylst2;

模板偏特化

1
2
3
4
5
6
7
8
9
template<class T,class Alloc=...>
class vector<bool,Alloc>{
...
}

template <typename T>
//指针
class C<T*>{
}

第27节

auto 关键字 必须得让编译器能推出你的变量是什么

1
2
3
4
5
list<string> c;
...
list<string>::iterator ite;
ite = find(c.begin(),c.end,target);
auto ite = find(c.begin(),c.end,target);
1
2
3
4
5
for (auto eleme : vec){
}

for (auto& eleme : vec){
}

第28节

1
2
3
4
5
6
7
int x = 0;
int* p = &x;
int& r = x; //r代表x 现在r, x 都是0
int x2 = 5;
//等于把5赋值给x
r = x2; //r 不能重新代表其它物体,现在r x都是5
int& r2 = r; //r2 x 都是5
1
2
3
double image(const double& im){...}
double image(const double im){...}
//不能共存 Ambiguity

const属于签名的一部分,有const和没有const可以并存

第30-31节

vptr和vtbl

先通过指针 找到函数表再找到第n个 再调用

(*(p->vptr)[n])(p);

(* p->vptr[n] )(p);

编译器三个条件就会动态绑定

1.指针调用 2.向上转型 3.虚函数

(*(this -> vptr)[n])(this);

第33-38节

当成员函数的const和 non-const版本同时存在,const object只会调用const版本,non-const object只会调用non-const版本

new 和 delete可以重载

1
2
3
4
inline void* operator new(size_t size)
{ return myAlloc(size);}
inline void operator delete(void* ptr)
{ myfree(ptr);}

可以对成员的new /delete 做重载,写到类里

如果想使用globals

1
2
3
Foo* pf = ::new Foo;
::delete pf
//将使用全局的new 和delete

数组在内存中的size是countsize + unit * count

我们可以重载class member operator new(),写多个版本,每个声明必须有独特的参数列,且第一个必须是size_t,其余参数是new指定的placement arguments为初值。小括号内的便是placement arguments

1
Foo* pf = new(300,'c') Foo;

可以重载class member operator delete(),写出多个版本,调不到,大师说老版本的能调到,在new异常的时候

operator new()在标准库的用处,多分配一些内存