特殊工具和技术

文章目录
  1. 1. 控制内存
    1. 1.1. 重载new和delete
    2. 1.2. 定位new表达式
  2. 2. 运行时类型识别
  3. 3. 枚举类型
  4. 4. 类成员指针
    1. 4.1. 数据成员指针
    2. 4.2. 成员函数指针
    3. 4.3. 将成员函数用作可调用对象
  5. 5. 嵌套类
  6. 6. union 一种节省空间的类

控制内存

重载new和delete

当我们使用new表达式时

1
2
string * sp = new string("a string");
string * arr = new string[10];

实际执行了三步:

  1. new 表达式调用 operator new 或operator new [] 标准库,分配一块足够大、原始的、未命名的内存空间。
  2. 编译器运行相应的构造函数,并传入初始值。
  3. 返回一个指向该对象的指针。

当我们使用delete表达式时

1
2
delete sp;
delete [] arr;
  1. 调用析构函数
  2. 调用名为operator delete 或者operator delete [] 释放空间。

发现new、delete表达式,如果对象是类类型,首先在类类型中查找,然后是全局作用域。也可以使用::new直接使用全局作用域的。

1
2
3
4
void * operator new(size_t);
void * operator new[](size_t);
void operator delete(void*) noexcept;
void operator delete[](void*) noexcept;

类作用域的new、delete是静态的。因为operator new 用在对象构造之前,operator delete 用在对象销毁后。而且不能操作类的任何成员。

new表达式和 operator new 函数:不能改变new表达式、delete表达式的含义。

malloc函数接受一个表示带分配字节数的size_t,返回指向分配空间的指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void * operator new(size_t size)
{
if(void* mem = malloc(size))
{
return mem;
}
else
{
throw bad_alloc();
}
}
void operator delete(void* mem) noexcept
{
free(mem);
}

定位new表达式

1
2
3
4
new (place_address) type
new (place_address) type (initializers)
new (place_address) type [size]
new (place_address) type [size] {braced initializer list}

定位new 使用 operation new (size_t ,void *)函数
定位new 可以构造对象,单不分配内存

申请释放空间 构造销毁对象
allcator
allocate construct
destroy deallocate
申请释放空间 构造销毁对象
new的形式
operator new 构造函数(定位new可以只构造对象,不申请空间)
free 析构函数(可以直接调用)

运行时类型识别

  1. typeid 运算符,返回表达式的类型
  2. dynamic_cast运算符 用于将基类指针或引用安全的转化为派生类的指针或者引用

当操作被定义为虚函数时,编译器将根据对象的动态类型自动的选择正确的版本 。

  1. dynamic_cast (e)
  2. dynamci_cast (e)
  3. dynamic_cast (e)

当typeid作用于指针时(而非指针所指的对象),返回的结果是该指针的静态编译时类型。

type_info 类的name成员函数返回一个C风格的字符串,表示对象的类型名字。type_info 只能通过typeid运算符创建。

枚举类型

枚举类型使我们可以将一组整形常量组织在一起。

  1. 限定作用域
  2. 不限定作用域
1
enum class 枚举名 { 逗号分隔的枚举列表};

枚举值可以不唯一,枚举成员是常量表达式。

和类一样,枚举也定义新的类型,也能定义变量。enum对象赋值必须使用该类型的一个枚举成员,或该类型的另一个对象。

指定enum的大小

1
2
enum intValue : unsigned long long 
{};

枚举类型的前置声明

类成员指针

成员指针,是指可以指向类的非静态成员的指针。一般情况下,指针指向一个对象,但是成员指针指示的是类的成员。

成员指针的类型囊括了类的类型、成员的类型。当初始化一个这样的指针时,我们另其指向类的某个成员,但是不指定该成员所属的对象。直到使用成员指针时,才提供成员所属的对象。

数据成员指针

声明成员指针时,必须包含成员所属的类

1
2
const string className:: * pdata;
pdata = &Screen::contents //指向某个非特定Screen对象的contents成员

当我们初始化一个成员指针或为成员指针赋值时,该指针并没有指向任何数据。成员指针指定了成员,而非该成员所属的对象。只有当解引用成员指针时,我们才提供对象的信息。 也就是解引用时候绑定到特定的对象上。

1
2
3
4
5
static const std::string Screen::*  data()
{
retrun &Screen::contents;
}
// data 指向Screen类const string 成员指针。

成员函数指针

char (Screen::*pmf2)(int,int ) const;

将成员函数用作可调用对象

成员函数指针不是可调用对象,调用前必须使用.或者->绑定到特定对象上。所以不能直接将成员函数指针传递给算法。


以下内容无法理解:

1. 可以使用function生成一个可调用对象。
2. 可以使用mem_fn生成一个可调用对象。
3. 使用bind 生成一个可调用对象。

嵌套类

一个类可以定义在另一个类的内部,前者称为嵌套类(nested class) ,后者称为嵌套类型(nested type)。

嵌套类是一个独立的类,与外层基本没有什么关系,特别是,外层类对象和嵌套类对象是相互独立的,嵌套类的对象不能包括任何外层类定义的成员;类似的,在外层类的对象也不能报考任何嵌套类定义的成员。嵌套类的名字在外层作用域内是可见的。之外不可见。 嵌套类对外层类的成员也没有特殊的访问权限。

union 一种节省空间的类

union可以定义多个数据成员,但在任何时刻,只有一个数据成员可以有值。union可以定义包括构造函数和析构函数在内的成员函数。但union不能继承自其它类,也不能作为基类使用。 不能有虚函数。