constructor copy constructor initialization and assignment operator

摘自C++ ARM的一段

Objects of classes with constructors can be initialized with a parenthesized expression list.

This list is taken as the argument list for a call of a constructor doing the initialization.

Alternatively a single value is specified as the initializer using the = operator. This value is used as the argument to a copy constructor.

Typically, that call of a copy constructor can be eliminated.


Overloading of the assignment operator has no effect on initialization.

Specifying initialization using = as normal expression evaluation followed by a copy operation (that is usually optimized away) has three effects:

 - The set of values acceptable for initialization and assignment will be identical except where the user specifically defines constructors and /or assignment operators to ensure that they are not. 

 - Access control is applied for the copy constructor (just as it is for assignment).

 - The use of a temporary and its possible elimination are explicitly allowed, giving implementers a degree of freedom that is sometimes needed.

Note that initialization and assignment are generally very different operations

Initialization occurs wherever an object is created. 

Assignment occurs when an assignment operator is used in an expression. An assignment operation will always invoke a predefined, user-defined, or default assignment operator. The left operand of an assignment is always a previously constructed object, whereas an object being initialized never is. Assignment operations typically rely on being invoked only for fully constructed objects.


Android Skia Bitmap中的一段代码

SkBitmap::SkBitmap() {
    sk_bzero(this, sizeof(*this));
}


SkBitmap::SkBitmap(const SkBitmap& src) {
    SkDEBUGCODE(src.validate();)
    sk_bzero(this, sizeof(*this));
    *this = src;
    SkDEBUGCODE(this->validate();)
}


SkBitmap::~SkBitmap() {
    SkDEBUGCODE(this->validate();)
    this->freePixels();
}


SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
    if (this != &src) {
        this->freePixels();
        memcpy(this, &src, sizeof(src));


        // inc src reference counts
        SkSafeRef(src.fPixelRef);
        SkSafeRef(src.fMipMap);


        // we reset our locks if we get blown away
        fPixelLockCount = 0;


        /*  The src could be in 3 states
            1. no pixelref, in which case we just copy/ref the pixels/ctable
            2. unlocked pixelref, pixels/ctable should be null
            3. locked pixelref, we should lock the ref again ourselves
        */
        if (NULL == fPixelRef) {
            // leave fPixels as it is
            SkSafeRef(fColorTable); // ref the user's ctable if present
        } else {    // we have a pixelref, so pixels/ctable reflect it
            // ignore the values from the memcpy
            fPixels = NULL;
            fColorTable = NULL;
            // Note that what to for genID is somewhat arbitrary. We have no
            // way to track changes to raw pixels across multiple SkBitmaps.
            // Would benefit from an SkRawPixelRef type created by
            // setPixels.
            // Just leave the memcpy'ed one but they'll get out of sync
            // as soon either is modified.
        }
    }


    SkDEBUGCODE(this->validate();)
    return *this;
}

Copy constructor SkBitmap::SkBitmap(const SkBitmap& src)中使用了operator assignment,红色的代码*this = arc,但是此时this仍是还没有fully constructed的对象,根据上面的段落 The left operand of an assignment is always a previously constructed object, whereas an object being initialized never is. Assignment operations typically rely on being invoked only for fully constructed objects. 那么调用的不是user-defined operator assignment?这样理解是一个误区。虽然是在拷贝构造函数中,但是*this = src语法上针对了fully constructed object的,编译器还没有智能到知道这个语句是在拷贝构造函数中使用,this是一个还未完全构造完毕的对象,所以*this = src in copy constructor仍然是调用的user-defined operator assignment。

拷贝构造函数编译出的指令如下,可以看到operator assignment的调用;

(gdb) disass 'SkBitmap::SkBitmap(SkBitmap const&)'
Dump of assembler code for function SkBitmap::SkBitmap(SkBitmap const&):
   0x00073758 <+0>: push {r3, r4, r5, lr}
   0x0007375c <+4>: mov r2, #40 ; 0x28
   0x00073760 <+8>: mov r4, r0
   0x00073764 <+12>: mov r5, r1
   0x00073768 <+16>: mov r1, #0
   0x0007376c <+20>: bl 0x68e58
   0x00073770 <+24>: mov r0, r4
   0x00073774 <+28>: mov r1, r5
   0x00073778 <+32>: bl 0x73684 <SkBitmap::operator=(SkBitmap const&)>
   0x0007377c <+36>: mov r0, r4
   0x00073780 <+40>: pop {r3, r4, r5, pc}
End of assembler dump.

[END]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值