C++ Primer 笔记18

1、C++中,内存分配和对象构造紧密纠缠,使用new表达式的时候,分配内存,并在该内存中构造一个对象;使用delete表达式的时候,调用析构函数撤销对象,并将对象所用内存返还给系统。
    C++提供下面两种方法分配和释放未构造的原始内存
allocator类,它提供可感知类型的内存分配。这个类支持一个抽象接口,以分配内存并随后使用该内存保存对象。
② 标准库中的 operator newoperator delete,它们分配和释放需要大小的原始的、未类型化的内存。
    C++还提供不同的方法在原始内存中构造和撤销对象
① allocator类定义了名为 constructdestroy的成员,其操作正如它们的名字所指出得那样:construct成员在未构造内存中初始化对象,destroy成员在对象上运行适当的析构函数。
② 定位new表达式接受指向未构造内存的指针,并在该空间中初始化一个对象或一个数组
③ 可以直接调用对象的析构函数来撤销对象,运行析构函数并不释放对象所在的内存
④ 算法 uninitialized_filluninitialized_copy像fill和copy算法一样执行,除了它们在目的地构造对象而不是给对象赋值之外。
2、现代C++程序一般应该使用allocator类来分配内存,它更安全更灵活。但是,在构造对象的时候,用new表达式比allocator::construct成员更灵活。
3、 allocator类 将内存分配和对象构造分开,当allocator对象分配内存的时候,它分配适当大小并排列成保存给定类型对象的空间。但是,它分配的内存是未构造的,allocator的用户必须分别construct和destroy放置在该内存中的对象。
4、 operator new函数和operator delete函数
    当使用new表达式
string *sp = new string("initialized");
的时候,实际上发生三个步骤。 首先, 该表达式调用名为operator new的标准库函数,分配足够大的原始的未类型化的内存,以保存指定类型的一个对象; 接下来,运行该类型的一个构造函数,用指定初始化式构造对象; 最后,返回指向新分配并构造的对象的指针。
    delete sp;
    当使用delete表达式delete sp;删除动态分配对象的时候,发生两个步骤。首先,对sp指向的对象运行适当的析构函数;然后,通过调用名为operator delete的标准库函数释放该对象所用的内存。
5、 new表达式与operator new函数
    标准库函数operator new和operator delete的命名容易让人误解。与其他operator函数(如operator=)不同,这些函数没有重载new或delete表达式,实际上,我们不能重定义new和delete表达式的行为。
    通过调用operator new函数执行new表达式获得内存,并接着在该内存中构造一个对象,通过撤销一个对象执行delete表达式,并接着调用operator delete函数,以释放该对象使用的内存。
6、operator new和operator delete接口
    operator new和operator delete函数有两个重载版本,每个版本支持相关的new表达式和delete表达式:
void *operator new(size_t);
void *operator new[](size_t);

void *operator delete(void*);
void *operator delete[](void*);
7、使用分配操作符函数
T * newelements = alloc.allocate(newcapacity);
可以重新编写为:
T * newelements = static<T *>(operator new[](newcapacity * sizeof(T)));
类似的
alloc.deallocate(elements, end - elements);
也可以重新编写为:
operator delete[](elements);
一般而言,使用allocator比直接使用operator new和operator delete函数更为类型安全。
8、类似于construct成员,有第三种new表达式,称为 定位new(placement new)。定位new表达式在已分配的原始内存中初始化一个对象,它与new的其他版本的不同之处在于,它不分配内存,相反,它接受指向已分配但未构造内存的指针,并在该内存中初始化一个对象。
    实际上,使用new表达式使我们能够在特定的、预分配的内存地址构造一个对象。
定位new表达式的形式是:
new (place_address) type
new (place_address) type (initializer-list)
其中place_address必须是一个指针,而initializer-list提供了初始化列表,以便在构造新分配的对象时使用。
alloc.construct(first_free, t);
可以使用等价的定位new表达式代替
new (first_free) T(t);
      定位new表达式初始化一个对象的时候,它可以使用任何构造函数,并直接建立对象。construct函数总是使用复制构造函数。
9、正如定位new表达式是使用allocator类的construct成员的低级选择,我们可以使用析构函数的显式调用作为调用destroy函数的低级选择。
alloc.destroy(ptr);
对于使用定位new表达式构造对象的程序,显式调用析构函数:
ptr->~T();
显式调用析构函数的效果是适当地清除对象本身。但是,并没有释放对象所占的内存,如果需要,可以重用该内存空间。
  调用operator delete函数不会运行析构函数,它只释放指定的内存。
10、默认情况下,new表达式通过调用由标准库定义的operator new版本分配内存,通过定义自己的名为operator new和operator delete的成员,类可以管理用于自身类型的内存。
    如果类定义了这两个成员中的一个,它也应该定义另一个。
    成员new和delete函数必须是静态的,因为它们要么在构造对象之前使用,要么在撤销对象之后使用,因此,这些函数没有成员数据可操纵,像人妖其他静态成员函数一样,new和delete只能直接访问所属类的静态成员。如果用new表达式调用全局operator new函数分配内存,则delete表达式也应该调用全局operator delete函数。
11、一个通用策略师预先分配一块原始内存来保存未构造的对象,创建新元素的时候,可以在一个预先分配的对象中构造;释放元素的时候,将它们放回预先分配对象的块中,而不是将内存实际返还给系统,这种策略常被称为维持一个 自由列表(freelist)。可以将自由链表实现为已分配但未构造的对象的链表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值