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;
}