Skia源码点滴

今天在看SkCanvas类的save()方法时看到两行code,有点不解,具体如下:

int SkCanvas::save() {
    this->willSave(kMatrixClip_SaveFlag);
    return this->internalSave(kMatrixClip_SaveFlag);
}

int SkCanvas::internalSave(SaveFlags flags) {
    int saveCount = this->getSaveCount(); // record this before the actual save

<strong>    MCRec* newTop = (MCRec*)fMCStack.push_back();
    new (newTop) MCRec(fMCRec, flags);    // balanced in restore()</strong></strong>

    fMCRec = newTop;

    if (SkCanvas::kClip_SaveFlag & flags) {
        fClipStack.save();
    }

    return saveCount;
}

加粗的两行code中,第二行的new关键字用法有些不解,然后百度之,解释如下:

关键字new在堆上动态创建一个对象时,它实际上做了三件事:获得一块内存空间、调用构造函数、返回正确的指针。

当然,如果我们创建的是简单类型的变量,那么第二步会被省略

假设有如下类A:

class A {    
int i; 
public:     A(int _i) :i(_i*_i) {}     
void Say()  { printf("i=%dn", i); 
} ; 
//调用new: 
A* pa = new A(3); 

那么上述动态创建一个对象的过程大致相当于以下三句话(只是大致上)

A* pa = (A*)malloc(sizeof(A)); 
pa->A::A(3); 
return pa; 
C++中一提到new,至少可能代表以下三种含义:new operator、operator new、placement new.

new operator就是我们平时所使用的new,其行为就是前面所说的三个步骤,我们不能更改它operator new是用来重载new操作符,示例如下:

class A { 
public:	  
	void* operator new(size_t size)	 {
		printf("operator new calledn");		  
		return ::operator new(size); //这里通过::operator new调用了原有的全局的new
	}
};

new的第三种形态——placement new是用来实现定位构造的,因此可以实现new operator三步操作中的第二步,也就是在

取得了一块可以容纳指定类型对象的内存后,在这块内存上构造一个对象

#include <new.h> 
void main() {
	char s[sizeof(A)];
	A* p = (A*)s;
	new(p) A(3); //p->A::A(3);
	p->Say();
}

对头文件<new>或<new.h>的引用是必须的,这样才可以使用placement new。这里
new(p) A(3);
这种奇怪的写法便是placement new了,它实现了在指定内存地址上用指定类型的构造函数来构造一个对象的功能,后面A(3)就是对构造函数的显式调用。这里不难发现,这块指定的地址既可以是栈,又可以是堆,placement对此不加区分。但是,除非特别必要,不要直接使用placement new ,这毕竟不是用来构造对象的正式写法,只不过是new operator的一个步骤而已。使用new operator地编译器会自动生成对placement new的调用的代码,因此也会相应的生成使用delete时调用析构函数的代码。如果是像上面那样在栈上使用了placement new,则必须手工调用析构函数,这也是显式调用析构函数的唯一情况: p->~A();

百度完毕。

<strong>    MCRec* newTop = (MCRec*)fMCStack.push_back();
    new (newTop) MCRec(fMCRec, flags);    // balanced in restore()</strong>

SkCanvas类的save()方法在new一个新的栈帧时提前在堆中分配好了内存,然后在这个分配好的内存中构造了栈帧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值