注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Tsecer的回音岛

Tsecer的博客

 
 
 

日志

 
 

C++中一种缺省初始化数组成员的语法  

2017-08-28 20:20:22|  分类: C/C++基础 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、问题场景
在一些头文件定义中,有时候可能需要定义一个包含了数组成员的简单结构。说它简单,是因为它其实只是相当于一个容器,不带有复杂逻辑,但是数组通常我们并不认为他是一个简单数组结构。例如,简单的数据结构定义为:
struct S
{
int iCount;
struct ComplexStruct *apArray[10];
};
这个结构中使用了数组,并且使用了比较“高危”的指针结构,由于指针的操作始终是一个敏感操作,所以希望为这个结构定义一个构造函数,在构造函数中将iCount成员初始化为0,并且将指针数组的成员全部初始化为NULL,这样可以在运行时多一层检测,避免使用者忘记对这个结构中的iCount或者指针初始化而造成灾难性的后果。

二、初始化的问题
初始化一个数组也不是一个复杂问题,主要调用memset即可。但是这里假设这个结构定义是一个非常基础的文件,我们不希望因为这个初始化而引入其它头文件包含。
对于构造函数中成员的初始化,大家都知道可以通过不带参数的member initializer来进行初始化,那么这个初始化对数组是否有效呢?C++对于这个内容的相关描述:

8.5 Initializers
5 To zeroinitialize storage for an object of type T means:
— if T is a scalar or pointertomember type, the storage is set to the value of 0 (zero) converted to T;
— if T is a nonunion class type, the storage for each nonstatic data member and each baseclass subobject is zeroinitialized;
— if T is a union type, the storage for its first nonstatic data member is zeroinitialized;
— if T is an array type, the storage for each element is zero initialized;
— if T is a reference type, no initialization is performed.

12.6.2 Initializing bases and members 
3 The expressionlist in a meminitializer is used to initialize the base class or nonstatic data member subobject denoted by the meminitializerid. The semantics of a meminitializer are as follows:
— if the expressionlist of the meminitializer is omitted, the base class or member subobject is default Initializing bases and members
initialized (see 8.5);
— otherwise, the subobject indicated by meminitializerid is directinitialized using expressionlist as the initializer (see 8.5)

其中的8.5节说明了T可以为一个array类型,所以在类的初始化函数中可以为一个数组成员进行初始化。并且这个是C++语言开始就支持的语法,不需要所谓的C11版本。

三、验证下
1、测试下添加了初始化的代码
#include <stdio.h>

struct A
{
int iCount;
struct Complext *apArray[10];
A():
iCount(), apArray()
{
}
void *operator new (long unsigned int sz, char * paddr)
{
return paddr;
}
};

char garray[100] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

int main()
{
A *pa = new (garray)A;
printf("a.iCount %d\n", pa->iCount);
for (int i = 0; i < 10 ; i++)
{
printf("a.apArray[%d] = %p\n", i, pa->apArray[i]);
}
}
tsecer@harry: g++ c++.default.init.cpp 
tsecer@harry: ./a.out 
a.iCount 0
a.apArray[0] = (nil)
a.apArray[1] = (nil)
a.apArray[2] = (nil)
a.apArray[3] = (nil)
a.apArray[4] = (nil)
a.apArray[5] = (nil)
a.apArray[6] = (nil)
a.apArray[7] = (nil)
a.apArray[8] = (nil)
a.apArray[9] = (nil)

2、注释掉初始化代码
tsecer@harry: cat c++.default.init.cpp 
#include <stdio.h>

struct A
{
int iCount;
struct Complext *apArray[10];
/*A():
iCount(), apArray()
{
}*/
void *operator new (long unsigned int sz, char * paddr)
{
return paddr;
}
};

char garray[100] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

int main()
{
A *pa = new (garray)A;
printf("a.iCount %d\n", pa->iCount);
for (int i = 0; i < 10 ; i++)
{
printf("a.apArray[%d] = %p\n", i, pa->apArray[i]);
}
}
tsecer@harry: g++ c++.default.init.cpp 
tsecer@harry: ./a.out 
a.iCount 1094795585
a.apArray[0] = 0x4141414141414141
a.apArray[1] = 0x4141414141414141
a.apArray[2] = 0x4141414141414141
a.apArray[3] = 0x4141414141414141
a.apArray[4] = 0x4141414141414141
a.apArray[5] = 0x4141414141414141
a.apArray[6] = 0x41414141414141
a.apArray[7] = (nil)
a.apArray[8] = (nil)
a.apArray[9] = (nil)

3、看下反汇编代码
tsecer@harry: cat c++.default.init.cpp 
#include <stdio.h>

struct A
{
int iCount;
struct Complext *apArray[10];
A():
iCount(), apArray()
{
}
void *operator new (long unsigned int sz, char * paddr)
{
return paddr;
}
};

char garray[100] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

int main()
{
A *pa = new (garray)A;
printf("a.iCount %d\n", pa->iCount);
for (int i = 0; i < 10 ; i++)
{
printf("a.apArray[%d] = %p\n", i, pa->apArray[i]);
}
}
tsecer@harry: g++ -S c++.default.init.cpp 
tsecer@harry: cat c++.default.init.s 
        .file   "c++.default.init.cpp"
        .section        .text._ZN1AC2Ev,"axG",@progbits,_ZN1AC5Ev,comdat
        .align 2
        .weak   _ZN1AC2Ev
        .type   _ZN1AC2Ev, @function
_ZN1AC2Ev:
.LFB1:
        .cfi_startproc
        .cfi_personality 0x3,__gxx_personality_v0
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movq    %rdi, -8(%rbp)
        movq    -8(%rbp), %rax
        movl    $0, (%rax)
        movq    -8(%rbp), %rax
        addq    $8, %rax
        movl    $9, %edx
        jmp     .L2
.L3:
        movq    $0, (%rax)
        addq    $8, %rax
        subq    $1, %rdx
.L2:
        cmpq    $-1, %rdx
        setne   %cl
        testb   %cl, %cl
        jne     .L3
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1:
        .size   _ZN1AC2Ev, .-_ZN1AC2Ev
        .weak   _ZN1AC1Ev
        .set    _ZN1AC1Ev,_ZN1AC2Ev
        .section        .text._ZN1AnwEmPc,"axG",@progbits,_ZN1AnwEmPc,comdat
        .weak   _ZN1AnwEmPc
        .type   _ZN1AnwEmPc, @function
_ZN1AnwEmPc:
.LFB3:
        .cfi_startproc
        .cfi_personality 0x3,__gxx_personality_v0
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movq    %rdi, -8(%rbp)
        movq    %rsi, -16(%rbp)
        movq    -16(%rbp), %rax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE3:
        .size   _ZN1AnwEmPc, .-_ZN1AnwEmPc
.globl garray
        .data
        .align 32
        .type   garray, @object
        .size   garray, 100
garray:
        .string "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        .zero   36
        .section        .rodata
.LC0:
        .string "a.iCount %d\n"
.LC1:
        .string "a.apArray[%d] = %p\n"
        .text
.globl main
        .type   main, @function
main:
.LFB4:
        .cfi_startproc
        .cfi_personality 0x3,__gxx_personality_v0
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        pushq   %rbx
        subq    $24, %rsp
        movl    $garray, %esi
        movl    $88, %edi
        .cfi_offset 3, -24
        call    _ZN1AnwEmPc
        movq    %rax, %rbx
        movq    %rbx, %rax
        movq    %rax, %rdi
        call    _ZN1AC1Ev
        movq    %rbx, -32(%rbp)
        movq    -32(%rbp), %rax
        movl    (%rax), %eax
        movl    %eax, %esi
        movl    $.LC0, %edi
        movl    $0, %eax
        call    printf
        movl    $0, -20(%rbp)
        jmp     .L8
.L9:
        movl    -20(%rbp), %edx
        movq    -32(%rbp), %rax
        movslq  %edx, %rdx
        movq    8(%rax,%rdx,8), %rdx
        movl    -20(%rbp), %eax
        movl    %eax, %esi
        movl    $.LC1, %edi
        movl    $0, %eax
        call    printf
        addl    $1, -20(%rbp)
.L8:
        cmpl    $9, -20(%rbp)
        setle   %al
        testb   %al, %al
        jne     .L9
        movl    $0, %eax
        addq    $24, %rsp
        popq    %rbx
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE4:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.6 20110731 (Red Hat 4.4.6-4)"
        .section        .note.GNU-stack,"",@progbits
tsecer@harry: 
  评论这张
 
阅读(20)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017