1、static成员
2、static成员优点
2、static成员函数
静态成员函数不能访问非静态成员原因:因为没有this指针。也不可以访问非静态成员函数。
可以通过对象来访问静态成员,但是不推荐这么使用,会让人误解成这个x_是属于对象的,但是静态成员是属于类的。
3、类/对象大小计算
一个虚函数,会增加4个字节,因为增加了一个虚函数表指针。
4、四种对象的作用域与生存期
bss区,即block started by symbol,因为未初始化的数据,在可执行文件中不占用空间,因为他们的初始值都为0,既然等于0,我们只需要一个符号来表示即可,不需要再为它们分配空间。
5、static用法总结
6、static与单例模式
禁止拷贝:将拷贝构造函数和等号运算符声明为私有的,这样就不允许拷贝和赋值
#include <iostream>
using namespace std
class Singleton
{
public:static Singleton* GetInstance(){if(instacne_== NULL){instacne_= new Singleton;}return instacne_}~Singleton(){cout<<"Singleton"<<endl;}
private:Singleton(const Singleton& other);Singleton& operator=(const Singleton& other)Singleton(){cout << "Singleton..." << endl;}static Singleton* instacne_;
}Singleton* Singleton::instacne_;int main(void)
{//Singleton sl;//Singleton s2;Singleton* sl = Singleton::GetInstance();Singleton* s2 = Singleton::GetInstance();//Singleton s3(*s1) // 调用拷贝构造函数return 0;
}
还有就是:在构造函数中,开辟的内存,在单例的这个对象生命周期结束的时候自动释放
方法一:提供一个释放内存的方法,主动调用
#include <iostream>
using namespace std
class Singleton
{
public:static Singleton* GetInstance(){if(instacne_== NULL){instacne_= new Singleton;}return instacne_}~Singleton(){cout<<"Singleton..."<<endl;}static void Free(){if (instance_ != NULL){delete instance_;}}
private:Singleton(const Singleton& other);Singleton& operator=(const Singleton& other)Singleton(){cout << "Singleton..." << endl;}static Singleton* instacne_;
}Singleton* Singleton::instacne_;int main(void)
{//Singleton sl;//Singleton s2;Singleton* sl = Singleton::GetInstance();Singleton* s2 = Singleton::GetInstance();//Singleton s3(*s1) // 调用拷贝构造函数Singleton::Free()return 0;
}
但是这样缺点也很明显:如果一个程序很多地方都使用了一个单例的对象,我们要释放,要在哪里释放?这个就不好控制了。我们需要的是在这个对象的声明周期结束的时候自动释放。
方法二:提供一个内嵌的嵌套类,然后再定义一个嵌套类的对象,当该单例对象的声明周期结束的时候,这个嵌套类的对象也就释放了。
#include <iostream>
using namespace std
class Singleton
{
public:static Singleton* GetInstance(){if(instance_== NULL){instance_= new Singleton;}return instance_}~Singleton(){cout<<”Singleton'<<endl;}//static void Free()//{// if (instance_ != NULL)// {// delete instance_;// }//}class Garbo{public:~Garbo(){if(Singleton::instance_!= NULL){delete instance_,}}}private:Singleton(const Singleton& other);Singleton& operator=(const Singleton& other)Singleton(){cout << "Singleton..." << endl;}static Singleton* instance_;static Garbo garbo_; // 利用对象的确定性析构:因为是在栈上的内存,生命周期结束的时候会自动调用~Garbo()这个析构函数
}Singleton* Singleton::instance_;
Singleton::Garbo Singleton::garbo_;int main(void)
{//Singleton sl;//Singleton s2;Singleton* sl = Singleton::GetInstance();Singleton* s2 = Singleton::GetInstance();//Singleton s3(*s1) // 调用拷贝构造函数return 0;
}
但是这样的情况下在类中又嵌套了一个类,看起来还是不美观。
方法三:auto_ptr智能指针,这个等后期再讲
方法四:这边是利用了一个static的特性,如果你第二次调用的话,那就不会再重新生成一个static对象,会用原来的。而且是一个局部静态对象,当程序结束的时候,就会调用析构函数销毁。但是这样,不是线程安全的。
#include <iostream>
using namespace std
class Singleton
{
public:static Singleton& GetInstance(){static Singleton instance;return instance;}~Singleton(){cout<<"~Singleton..."<<endl;}private:Singleton(const Singleton& other);Singleton& operator=(const Singleton& other)~Singleton(){cout << "Singleton..." << endl;}}int main(void)
{Singleton& sl = Singleton::GetInstance();Singleton& s2 = Singleton::GetInstance();return 0;
}
7、const成员函数
const也可以构成重载。
#include <iostream>
using namespace std;class Test
{
public:Test(int x):x_(x){}int GetX() const{cout << "const GetX ..." << endl;//x_ = 100; // 这样会报错return x_;}int GetX(){cout << "GetX ..." << endl;return x_;}
private:int x_;
}int main(void)
{return 0;
}
8、const对象
因为const对象不允许修改,所以如果const对象允许调用非const成员函数,那就有被修改的风险。
#include <iostream>
using namespace std;class Test
{
public:Test(int x):x_(x){}int GetX() const{cout << "const GetX ..." << endl;//x_ = 100; // 这样会报错return x_;}int GetX(){cout << "GetX ..." << endl;return x_;}
private:int x_;
}int main(void)
{const Test t(10);t.GetX();Test t2(20);t2.GetX();return 0;
}
9、mutable
#include <iostream>
using namespace std;class Test
{
public:Test(int x):x_(x){}int GetX() const{cout << "const GetX ..." << endl;//x_ = 100; // 这样会报错return x_;}int GetX(){cout << "GetX ..." << endl;return x_;}void OutPut() const{cout << "x = " << x_ << endl;outputTimes_++;}int GetOutputTimes() const{return outputTimes_;}
private:int x_;mutable int outputTimes_;
}int main(void)
{const Test t(10);t.GetX();Test t2(20);t2.GetX();t.Output();t.Output();cout << t.GetOutputTimes() << endl;return 0;
}