直接return array只会返回第一个元素哦!下面介绍四种返回数组方法ios
#include <iostream> #include <string.h> #include <math.h> #define CITY_NUM 11000 class LbsIndexCity{ public: LbsIndexCity(int city_id):m_city_id(city_id){} int get_city_id(){ return m_city_id; } private: int m_city_id; }; LbsIndexCity* m_city[CITY_NUM]; void add_m_city(int city_id){ m_city[101]=new LbsIndexCity(city_id); } /* 1. LbsIndexCity* (* get_m_city())[CITY_NUM]{ return &m_city; } */ /* 2. typedef LbsIndexCity* arrT[CITY_NUM]; arrT * get_m_city(){ return &m_city; } */ /* 3. auto get_m_city() -> LbsIndexCity*(*)[CITY_NUM]{ return &m_city; } */ LbsIndexCity* arrT[CITY_NUM]={nullptr}; decltype(arrT) *get_m_city(){ return &m_city; } int main() { add_m_city(1001); LbsIndexCity* (*m_city)[CITY_NUM] = get_m_city(); for(int city_id =0; city_id < CITY_NUM; city_id++) { if((*m_city)[city_id] == NULL){ continue ; }else{ std::cout <<(*m_city)[city_id]->get_city_id()<<std::endl; } } std::cout << "cyy,Hello, World!" <<std::endl; return 0; }
1.饿汉实现数组
/*饿汉实现 * 因为要进行线程同步,因此在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,能够实现更好的性能。这是以空间换时间 * 显示调用Destroy * */ template <class T> class singleton{ private: static T* p; singleton(){} ~singleton(){} public: static T* GetInstance(); static void Destroy(); //须要在退出时显示调用 }; template <class T> T* singleton<T>::p = new T(); template <class T> T* singleton<T>::GetInstance(){ return p; } template <class T> void singleton<T>::Destroy(){ if(p == nullptr){ return ; } std::cout<<"delete~"<<std::endl; delete p; }
2.懒汉实现 pthread_once,atexit(Destroy);多线程
#include "pthread.h" #include <stdlib.h> #include <iostream> /*懒汉实现 * 在访问量较小时,采用懒汉实现,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化 * 显示调用析构 * */ template <class T> class singleton2 { protected: singleton2(){}; private: singleton2(const singleton2&){}; singleton2& operator=(const singleton2&){}; static T* m_instance; static pthread_once_t m_once; //static pthread_mutex_t g_mutex; public: static void Init(); static void Destroy(); static T* GetInstance(); }; template <class T> void singleton2<T>::Destroy(){ if(m_instance == nullptr){ return ; } delete m_instance; } template <class T> void singleton2<T>::Init() { m_instance = new T(); atexit(Destroy); } template <class T> T* singleton2<T>::GetInstance() { pthread_once(&m_once,Init); return m_instance; } template <class T> pthread_once_t singleton2<T>::m_once = PTHREAD_ONCE_INIT; template <class T> T* singleton2<T>::m_instance = NULL;
2.懒汉实现 锁,atexit(Destroy);函数
template <class T> class singleton2 { protected: singleton2(){}; private: singleton2(const singleton2&){}; singleton2& operator=(const singleton2&){}; static T* m_instance; static pthread_once_t m_once; //static pthread_mutex_t g_mutex; public: static void Init(); static void Destroy(); static T* GetInstance(); }; template <class T> void singleton2<T>::Destroy(){ if(m_instance == nullptr){ return ; } delete m_instance; } template <class T> T* singleton2<T>::m_instance = NULL; template <class T> pthread_mutex_t singleton2<T> ::g_mutex = PTHREAD_MUTEX_INITIALIZER; template <class T> T* singleton2<T>::GetInstance() { if( m_instance == NULL) { pthread_mutex_lock(&g_mutex); if( m_instance == NULL) { T* ptmp = new T(); m_instance = ptmp; //防止多线程顺序 atexit(Destroy) } pthread_mutex_unlock(&g_mutex); } return m_instance; }
4.懒汉 静态对象,保证只有一个,不用new,不须要析构性能
template <class T> class singleton3 { protected: singleton3(){}; private: singleton3(const singleton3&){}; singleton3& operator=(const singleton3&){}; static pthread_mutex_t g_mutex; public: static T* GetInstance(); }; template <class T> T* singleton3<T>::GetInstance() { pthread_mutex_lock(&g_mutex); static T _instance; pthread_mutex_unlock(&g_mutex); return &_instance; } template <class T> pthread_mutex_t singleton3<T> ::g_mutex = PTHREAD_MUTEX_INITIALIZER;
5.测试函数测试
#include "pthread.h" #include <stdlib.h> #include <iostream> class ApplicationImpl { public: ApplicationImpl() { std::cout << "ApplicationImpl ..." << std::endl; } ~ApplicationImpl() { std::cout << "~ApplicationImpl ..." << std::endl; } void Run() { std::cout << "Run ..." << std::endl; } }; typedef singleton3 < ApplicationImpl > Application; void *routine(void *arg) { Application::GetInstance()->Run(); } int main(void) { Application::GetInstance()->Run(); pthread_t tid; int ret; if ((ret = pthread_create(&tid, NULL, routine, NULL)) != 0) { fprintf(stderr, "pthread create: %s\n", strerror(ret)); exit(EXIT_FAILURE); } Application::GetInstance()->Run(); pthread_join(tid, NULL); // Application::Destroy(); //第一个须要显示调用 return 0; }
以上程序的几点说明:
1.静态成员与类自己相关,不是对象(成员函数不能声明const,不能用this指针)。可用返回类类型,普通只能是类&或类*,可以使用静态成员做为默认实参
2.在类外部定义静态成员不能重复static关键字
3.静态成员函数能够在类内/外定义(内部是内联的)
静态成员不是构造函数初始化的,通常再也不内部初始化,const类型须要在内部初始化时,也应该在类外部定义下
4.const未初始化的,要在构造函数显示初始化
5.A a;默认构造函数,不需手动事发昂,析构函数自动执行
A= New A(); 只有delete释放,堆,一次初始化屡次使用,可作返回等,不适合频繁调用
A* a=NULL; 普通指针,未通过初始化,不需delete
模板:优化
经过友元+虚继承实现。F是N的友元,能够调用N的私有初始化函数,F能够构造,若M要继承F,因为F是虚继承,里边直接包含N的虚表,会直接调用N的构造函数为private报错。若F不是虚继承,F的函数内会绑定N的构造函数在F内,友元能够调用this
template<typename T> class NoneInherit { friend T; private: NoneInherit() { } ~NoneInherit() { } }; class Finalclass: virtual public NoneInherit<Finalclass> { public: Finalclass() { } ~Finalclass() { } };
若用基类指针,赋值子类对象的方法调用,对于没有声明被声明成虚函数的方法,代码中的调用在编译时就已经被绑定了实现,绑定的是基类的实现。虚函数会增长一个vftable虚函数表,在动态运行时调用(注意只有在用过指针和引用时才须要动态绑定)。线程
内联函数是在编译时期展开,而虚函数的特性是运行时才动态联编,因此二者矛盾,不能定义内联函数为虚函数。
构造函数需在编译时刻,由于需构造出个对象,才能执行动做。因此不能将构造函数定义为虚函数。virtual意味着派生类能够改写其动做。派生类的构造函数会先执行基类的构造函数而不是取代基类构造函数
静态成员函数属于一个类而非某一对象,没有this指针,它没法进行对象的判别。
虚析构函数和其余虚函数同样高指针
虚函数和重载函数。
在基类中用关键词“virtual”声明成员函数,而后在派生类中正式定义或从新定义此函数,其中要求函数名、函数类型、参数类型和个数必须与基类虚函数相同。
函数重载在同一做用域(如:类)中,几个函数名字相同但参数列表(参数类型,参数个数)不全相同。针对某个类里面的同名函数而言,而虚函数是针对基类和派生类之间同名函数而言。
在同一类族中不能再定义一个非virtual的但与虚函数具备相同参数(类型和个数)和返回类型的同名函数。
纯虚函数 double xx() const=0;抽象基类,不能建立对象
若出现菱形继承,D->B虚继承,C虚继承->A,D会由于B,C共同继承A有公共的一些成员变量和方法是相同的。若是用A指针指向D类的实例,则对于共同的成员变量和方法,编译器没法判断是要使用B类中的仍是使用C类中的。增长虚指针,与虚函数处理思想同样,和虚函数自己不要紧。
非虚继承
class LandAnimal size(12): 1> +--- 1> 0 | +--- (base class Animal) 1> 0 | | {vfptr} 1> 4 | | name 1> | +--- 1> 8 | numLegs 1> +--- 1> 1> LandAnimal::$vftable@: 1> | &LandAnimal_meta 1> | 0 1> 0 | &Animal::breathe 1> 1 | &LandAnimal::run 1> 1> class Mammal size(12): 1> +--- 1> 0 | +--- (base class Animal) 1> 0 | | {vfptr} 1> 4 | | name 1> | +--- 1> 8 | numBreasts 1> +--- 1> 1> Mammal::$vftable@: 1> | &Mammal_meta 1> | 0 1> 0 | &Animal::breathe 1> 1 | &Mammal::milk 1> 1> class Human size(28): 1> +--- 1> 0 | +--- (base class Mammal) 1> 0 | | +--- (base class Animal) 1> 0 | | | {vfptr} 1> 4 | | | name 1> | | +--- 1> 8 | | numBreasts 1> | +--- 1> 12 | +--- (base class LandAnimal) 1> 12 | | +--- (base class Animal) 1> 12 | | | {vfptr} 1> 16 | | | name 1> | | +--- 1> 20 | | numLegs 1> | +--- 1> 24 | race 1> +--- 1> 1> Human::$vftable@Mammal@: 1> | &Human_meta 1> | 0 1> 0 | &Animal::breathe 1> 1 | &Human::milk 1> 1> Human::$vftable@LandAnimal@: 1> | -12 1> 0 | &Animal::breathe 1> 1 | &Human::run
虚继承:
1> class LandAnimal size(20): 1> +--- 1> 0 | {vfptr} 1> 4 | {vbptr} 1> 8 | numLegs 1> +--- 1> +--- (virtual base Animal) 1> 12 | {vfptr} 1> 16 | name 1> +--- 1> 1> LandAnimal::$vftable@LandAnimal@: 1> | &LandAnimal_meta 1> | 0 1> 0 | &LandAnimal::run 1> 1> LandAnimal::$vbtable@: 1> 0 | -4 1> 1 | 8 (LandAnimald(LandAnimal+4)Animal) 1> 1> LandAnimal::$vftable@Animal@: 1> | -12 1> 0 | &Animal::breathe 1> 1> class Mammal size(20): 1> +--- 1> 0 | {vfptr} 1> 4 | {vbptr} 1> 8 | numBreasts 1> +--- 1> +--- (virtual base Animal) 1> 12 | {vfptr} 1> 16 | name 1> +--- 1> 1> Mammal::$vftable@Mammal@: 1> | &Mammal_meta 1> | 0 1> 0 | &Mammal::milk 1> 1> Mammal::$vbtable@: 1> 0 | -4 1> 1 | 8 (Mammald(Mammal+4)Animal) 1> 1> Mammal::$vftable@Animal@: 1> | -12 1> 0 | &Animal::breathe 1> 1> class Human size(36): 1> +--- 1> 0 | +--- (base class Mammal) 1> 0 | | {vfptr} 1> 4 | | {vbptr} 1> 8 | | numBreasts 1> | +--- 1> 12 | +--- (base class LandAnimal) 1> 12 | | {vfptr} 1> 16 | | {vbptr} 1> 20 | | numLegs 1> | +--- 1> 24 | race 1> +--- 1> +--- (virtual base Animal) 1> 28 | {vfptr} 1> 32 | name 1> +--- 1> 1> Human::$vftable@Mammal@: 1> | &Human_meta 1> | 0 1> 0 | &Human::milk 1> 1> Human::$vftable@LandAnimal@: 1> | -12 1> 0 | &Human::run 1> 1> Human::$vbtable@Mammal@: 1> 0 | -4 1> 1 | 24 (Humand(Mammal+4)Animal) 1> 1> Human::$vbtable@LandAnimal@: 1> 0 | -4 1> 1 | 12 (Humand(LandAnimal+4)Animal) 1> 1> Human::$vftable@Animal@: 1> | -28 1> 0 | &Human::breathe
1.在同一层次的继承中,虚拟继承的构造函数要先于非虚拟继承的构造函数,在同一层的全部非虚拟继承的类中,其构造函数的执行顺序是先左后右,一样的在同一层全部非虚拟继承的类中,构造函数的执行也是先左后右,和类的定义顺无关
class c :virtual public e, public a, public b, virtual public d
=》e,d,a,b,c
2.类成员变量,初始化顺序与定义顺序一致
public: int a1; int a2; a(int x,int y) :a2(y),a1(x){}
=>a1,a2
3.
变量能够分为:全局变量、静态全局变量、静态局部变量和局部变量。
按存储区域分,全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区。
按做用域分,全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,而且程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,可是函数返回后失效
全静态变量,全局变量,在main以前初始化,在编译时分配内存(类中静态变量要在类外定义,对于const能在编译时肯定在编译时执行,不然同理),局部静态变量在调用到具体函数时初始化。
4.析构函数与构造函数调用顺序相反。(new 调用delete时,局部变量非静态 函数退出后 全局变量/静态变量(不管局部仍是全局) 程序退出时)
任何在类的说明部分定义的函数都会被自动的认为是内联函数。
宏在预编译期间处理(字符串替换),内联函数是编译期间插入(省去函数栈分配);内联函数有参数检查等;内联函数会插入到调用方,没必要寻址。
volatile:cpu寄存器不优化,编译器不优化。仍是没办法解决多线程指令顺序。通常用于文件映射等
https://liam.page/2018/01/18/...