返回数组的形式
直接return array只会返回第一个元素哦!下面介绍四种返回数组方法
#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内,友元可以调用
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时,局部变量非静态 函数退出后 全局变量/静态变量(无论局部还是全局) 程序退出时)
inline与宏
任何在类的说明部分定义的函数都会被自动的认为是内联函数。
宏在预编译期间处理(字符串替换),内联函数是编译期间插入(省去函数栈分配);内联函数有参数检查等;内联函数会插入到调用方,不必寻址。
volatile:cpu寄存器不优化,编译器不优化。还是没办法解决多线程指令顺序。一般用于文件映射等
https://liam.page/2018/01/18/...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。