auto i = {1, 2, 3, 4};
cout << typeid(i).name()<
c++11中的vector
2、mapvector
和initializer_list的区别
- vector有push_back操作,其有reserve重新new内存空间,是在堆中进行的操作,而initializer_list是在栈上,其内部只有begin和end函数,函数内不能修改这些数值
- vector会发生拷贝,而initializer_list是指针语义,里面的元素不会被拷贝
3、为什么析构函数是虚函数
- map没有赋值的时候是被初始化为0的
std::mapm; int a = m[1110]; //输出 a为0
- map自定义键值类型
map底层的实现是红黑树,红黑树具有二叉搜索树的性质,map在插入的时候具有对key进行排序的功能,这是因为c++的基本类型有默认的比较方式,即便是string类型,其可以自动排序那是因为string内部实现了operator < 的重载。
类或结构体中重载operator<
#include#include
4、static介绍当基类的指针指向派生类的时候要将基类的析构函数设置为虚函数,这样是为了防止派生类无法析构导致内存泄露
- 基类析构未使用虚函数
#includeusing namespace std; class base { public: base() {}; ~base() { cout << "Output from the destructor of class base!" << endl; }; void DoSomething() { cout << "Do something in class base!" << endl; }; }; class Derived : public base { public: Derived() {}; ~Derived() { cout << "Output from the destructor of class Derived!" << endl; }; void DoSomething() { cout << "Do something in class Derived!" << endl; } }; int main() { base *p = new Derived; p->DoSomething(); delete p; return 0; } 上述代码,未使用virtual,输出的结果没有进入派生类的析构函数中,会导致内存泄露的发生。
- 基类析构函数使用虚函数
#includeusing namespace std; class base { public: base() {}; virtual ~base() { cout << "Output from the destructor of class base!" << endl; }; void DoSomething() { cout << "Do something in class base!" << endl; }; }; class Derived : public base { public: Derived() {}; ~Derived() { cout << "Output from the destructor of class Derived!" << endl; }; void DoSomething() { cout << "Do something in class Derived!" << endl; } }; int main() { base *p = new Derived; p->DoSomething(); delete p; return 0; } 根据多态的性质,在释放的时候就是先析构派生类,然后在析构基类
- 静态资源是类初始化的时候加载的,
- 而非静态资源是类实例化对象的时候加载的,
- 类的初始化早于类实例化对象
5、私有构造函数
- 静态成员函数属于整个类,在类实例化之前就已经分配空间了。而非静态成员必须在类实例化之后才能有内存空间。
#includeusing namespace std; class Point { public: void init() { } static void output() { //error 报非静态成员引用必须与特定对象对应,即静态成员函数不能调用非静态变量 cout << m_x << endl; } static void output1() { //ok 没有非静态成员就可以 cout << “hello”<< endl; } private: int m_x; }; void main() { Point pt; pt.output(); }
- 非静态成员函数可以调用静态变量,前提是静态变量要提前在类外初始化
#includeclass Point { public: Point() { m_nPointCount++; } ~Point() { m_nPointCount--; } static void output() { printf("%dn", m_nPointCount); } private: static int m_nPointCount; int m_1; }; int Point::m_nPointCount = 0; //初始化则ok,否则不ok void main() { Point pt; pt.output(); }
- 将构造函数私有化之后就不能在类的外部构造对象了,也不能在外部构造子类的对象了。但是可以通过一个public的static静态函数来访问类中定义的函数和静态成员,单例模式就是这样。
- 这样的好处就是可以阻止用户在类外调用析构该对象了。
#includeusing namespace std; class Singleton { private: Singleton() { cout << "Singleton" << endl; } public: static Singleton* getInstance() { if (m_instance == nullptr) m_instance = new Singleton; return m_instance; } //析构函数中释放,delete是不对的,析构函数中的delete会再次进入析构,导致循环调用了 ~Singleton() { //if (m_instance) //{ // cout << "~Singleton" << endl; // delete m_instance; // m_instance = nullptr; //} } //释放 void Release() { if (m_instance) { cout << "~Singleton" << endl; delete m_instance; m_instance = nullptr; } } private: static Singleton *m_instance; }; Singleton *Singleton::m_instance = nullptr; int main() { Singleton* m1 = Singleton::getInstance(); Singleton* m2 = Singleton::getInstance(); m1->Release(); //error //delete m1; //m1 = nullptr; } 也可以通过在类内部定义一个静态成员变量来释放单例的内存,静态成员变量会在程序结束的时候自动进入析构释放资源。 所以该静态成员变量是需要是一个实现析构的类。
程序在结束的时候,系统会自动析构所有的全局变量和所有的类的静态成员变量。利用这个特征,我们可以在单例类中定义一个静态成员变量,而它的唯一工作就是在析构函数中删除单例类的实例。
#includeusing namespace std; class Singleton { private: Singleton() { cout << "Singleton" << endl; } public: static Singleton* getInstance() { if (m_instance == nullptr) m_instance = new Singleton; return m_instance; } ~Singleton() { //if (m_instance) //{ // cout << "~Singleton" << endl; // delete m_instance; // m_instance = nullptr; //} } void Release() { if (m_instance) { cout << "~Singleton" << endl; delete m_instance; m_instance = nullptr; } } class CRelease { public: ~CRelease() { if (m_instance) { cout << "~Singleton" << endl; delete m_instance; m_instance = nullptr; } } private: static CRelease m_re; }; private: static Singleton *m_instance; }; Singleton *Singleton::m_instance = nullptr; Singleton::CRelease mRelease; //静态变量需要初始化,要不然进不去析构函数 int main() { Singleton* m1 = Singleton::getInstance(); Singleton* m2 = Singleton::getInstance(); //m1->Release(); }
shared_ptr并自定义deleter
#include6、thread的拷贝、转移问题#include using namespace std; mutex mtx; class Singleton { public: static shared_ptr getInstance() { //双重检查,避免单重检查每次都加锁 if (m_instance == nullptr) { lock_guard lck(mtx); if(m_instance == nullptr) m_instance = make_shared (); } return m_instance; } private: static void Release(Singleton *s) { cout << "Release" << endl; delete s; } private: static shared_ptr m_instance; }; shared_ptr Singleton::m_instance(nullptr, Singleton::Release); int main() { shared_ptr m1 = Singleton::getInstance(); shared_ptr m2 = Singleton::getInstance(); }
c++11中的thread不能被拷贝,其内部没有拷贝构造函数,thread的源码如下:
thread(thread&& _Other) noexcept : _Thr(_Other._Thr) { // move from _Other _Thr_set_null(_Other._Thr); } thread& operator=(thread&& _Other) noexcept { // move from _Other return (_Move_thread(_Other)); } thread(const thread&) = delete; thread& operator=(const thread&) = delete;将thread传递的时候要使用右值引用和move函数
#include#include using namespace std; class CThread { public: CThread(thread &th):m_th(move(th)) { cout << "nCThread, id:" << m_th.get_id() << ", joinable status is:" << m_th.joinable() << endl; } ~CThread() { cout << "~CThread" << endl; m_th.join(); } CThread(const CThread &th) = delete; CThread &operator=(const CThread &th) = delete; private: thread m_th; }; void func() { cout << "func" << endl; } int main() { thread t(func); cout << "thread before move, id:" <



