2010/10/28

2010/10/28

关键字:newdeleteallocator

string *sp = new string(“123456”);  //new表达式

实际有3个步骤:

1.     调用operator new标准库函数,分配足够大的原始的未类型化的内存,以保存指定类型的一个对象

2.      运行该类型的适当的构造函数,用指定初始化式构造对象

3.      返回新分配并构造的对象的地址

delete sp;     //delete表达式

实际有2个步骤:

1.      sp所指向的对象运行适当的析构函数

2.     通过调用operator delete的标准库函数释放该对象所用的内存

operator newoperator delete函数有两个重载版本,每个版本支持相关的newdelete表达式:

void *operator new(size_t);     //allocate an object

void *operator new[](size_t);   //allocate an array

void *operator delete(void*);   //free an object

void *operator delete[](void*); //free an array

 

除了new intnew int[]还有第三种new表达式,定位new(placement new).

new(place_address) type

new(place_address) type (initializer-list)

其中place_address必须是一个指针,而initializer-list提供了(可能为空)初始化列表以便在构造新分配的对象时使用。

例如:

allocator<string> alloc;

string *sp = alloc.allocate(3);         //分配3string的空间

new (sp) string;                        //直接在sp内存中构造空的string对象

new (sp+1) string("123");               //直接在sp+1内存中构造有初始化值的string对象

alloc.construct(sp+2, string("123"));   //构造string对象并拷贝到sp+2位置

如果类定义了自己的成员newdelete,还是可以通过全局作用域操作符调用newdelete表达式:

Type *p = ::new Type;

::delete p;

 

除了operator newoperator delete,还可以使用allocator类分配和释放未构造的原始内存以及构造和析构对象.

allocator类是一个模板,提供了类型化的内存分配以及对象构造和撤销.newdelete表达式和标准库函数都是使用void*类型的.

标准allocator类与定制算法

allocator<T> a;

定义名为aallocator对象

a.allocate(n);

分配原始内存以保存T类型的n个对象

a.deallocate(p, n);

释放地址p处的nT类型对象的内存,事先析构这些对象是用户的责任

a.construct(p, t);

T*指针p所在的内存中构造一个新对象,并调用T类型的拷贝构造函数,t初始化新对象

a.destroy(p);

调用T*指针p所指对象的析构函数

uninitialized_copy(begin, end, begin2);

从迭代器begin,end指定的输入范围将元素复制到从迭代器begin2开始的未构造的原始内存中.该函数在目的内存构造元素,而不是给它们赋值.用户需要确保begin2指出的目的内存足以保存输入范围中的元素的副本

uninitialized_fill(begin, end, t);

beginend指定的范围内原始内存初始化为t的副本,使用拷贝构造函数

uninitialized_fill_n(begin, end, t, n);

beginend指定的范围内至多nT类型对象大小的原始内存初始化为t的副本,范围至少nT类型对象大小的原始内存,使用拷贝构造函数,同样是用户确保n的合法性

对未构造的内存中的对象进行赋值而不是初始化,其行为是未定义的。赋值涉及先删除现存对象,如果没有现存对象赋值操作中的动作会造成灾难性的后果。

allocator类将内存分配和对象构造分开,并且allocate函数分配的内存是连续的.allocate类只是定义了一系列操作内存的接口,本身并不保存内存地址.

可以结合allocator类理解vertor类中的内存是如何分配的。

为了获得可接受的性能,vector预先分配比所需元素更多的空间.每个将元素增加到vector中的成员函数都会检查是否有可用空间容纳当前元素.如果有,该函数在预分配内存中的下一个可用位置初始化一个对象;否则就重新分配vector:vecor获得新空间后,将现存元素复制到新空间,增加新元素并释放旧空间.

#include <memory>

 

template<class T> class MyVector

{

public:

    MyVector():Begin(0),FreeBegin(0),End(0){}

    void push_back(const T&);

    //...

private:

    static std::allocator<T> Alloc;

    void Reallocate();

    T *Begin;

    T *FreeBegin;

    T *End;

    //...

};

需要解释下三个迭代器的作用:

Begin是内存首地址,FreeBegin是未构造内存的首地址,End是内存末尾.当容器中没有元素时,BeginFreeBegin指向一处,都指向内存首地址.

容器的size(实际使用的元素的数目)为FreeBegin-Begin.

容器的capacity(在需要重新分配之前,可容纳的元素总量)为End-Begin.

自由空间(在需要重新分配之前,可以增加的元素数目)为End-FreeBegin.

下面是成员函数实现:

template<class T>

void MyVector<T>::push_back(const T& t)

{

    if (FreeBegin == End)

        Reallocate();

    Alloc.construct(FreeBegin, t);

    ++FreeBegin;

}

 

template<class T>

void MyVector<T>::Reallocate()

{

    std::size_t size = FreeBegin - Begin;               //暂时用size_t

    std::size_t newCapacity = 2 * max(size, 1);     //计算新空间大小

 

    T *pNewBegin = Alloc.allocate(newCapacity);     //分配新空间

    uninitialized_copy(Begin, FreeBegin, pNewBegin);    //拷贝现有元素到新空间

 

    for (T *p = FreeBegin; p!=Begin;)                   //析构旧空间中的元素

        Alloc.destroy(--p);

 

    if (Begin)

        Alloc.deallocate(Begin, End-Begin);         //释放旧空间

 

    Begin = pNewBegin;

    FreeBegin = Begin + size;

    End = Begin + newCapacity;

}

算法采用简单却高效的方式,每次重新分配现有内存2倍的空间,如果容器为空,则分配2个元素的空间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
(1)根据所提供的日期,提取月份 (2)请对2010年各地区各产品的销售情况进行分析(图表展现) (3)请对各个业务员的业绩进行分析(图表展现) (4)请对各季度的业绩进行分析(图表展现),同时给出商家一些可以提高销售业绩的建议 日期 地区 业务员 品名 销量(个) 单价(元) 销售额(元) 月份 2010/1/6 A 张三 订书机 95 25 2375 2010/1/23 B 王五 钢笔 50 35 1750 2010/2/9 B 周六 钢笔 36 35 1260 2010/2/26 B 周六 笔记本 360 15 5400 2010/3/15 C 田七 订书机 600 25 15000 2010/4/1 A 李四 铅笔 930 0.5 465 2010/4/18 B 周六 订书机 740 25 18500 2010/5/5 B 周六 钢笔 960 35 33600 2010/5/22 C 田七 钢笔 530 35 18550 2010/6/8 A 李四 笔记本 410 15 6150 2010/6/25 B 王五 订书机 940 25 23500 2010/7/12 A 张三 铅笔 280 0.5 140 2010/7/29 A 张三 订书机 81 25 2025 2010/8/15 A 张三 钢笔 35 35 1225 2010/9/1 B 周六 钢笔 65 35 2275 2010/9/18 A 李四 笔记本 93 15 1395 2010/10/5 B 周六 订书机 28 25 700 2010/10/22 A 李四 铅笔 640 0.5 320 2010/11/8 A 李四 订书机 870 25 21750 2010/11/25 B 周六 钢笔 620 35 21700 2010/12/12 B 周六 钢笔 550 35 19250 2010/12/29 A 李四 笔记本 74 15 1110 2010/1/15 B 王五 订书机 46 25 1150 2010/2/1 B 王五 铅笔 870 0.5 435 2010/2/18 A 张三 订书机 32 25 800 2010/3/7 C 赵大 钢笔 70 35 2450 2010/3/24 B 王五 钢笔 50 35 1750 2010/4/10 B 王五 钢笔 66 35 2310 2010/4/27 A 李四 笔记本 96 15 1440 2010/5/14 B 周六 笔记本 53 15 795 2010/5/31 B 周六 订书机 80 25 2000 2010/6/17 B 周六 订书机 27 25 675 2010/7/4 A 李四 铅笔 620 0.5 310 2010/7/21 B 周六 铅笔 550 0.5 275 2010/8/7 B 周六 订书机 42 25 1050 2010/8/24 C 田七 订书机 76 25 1900 2010/9/10 B 王五 钢笔 69 35 2415 2010/9/27 C 赵大 钢笔 76 35 2660 2010/10/14 C 赵大 钢笔 57 35 1995 2010/10/31 B 王五 钢笔 47 35 1645 2010/11/17 B 王五 笔记本 110 15 1650 2010/12/4 B 王五 笔记本 94 15 1410 2010/12/21 B 周六 笔记本 28 15 420 excel
最新发布
07-17

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值