打印

深入浅出: C 与 C++ 中“结构直接复制”的探讨

[复制链接]
21568|95
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 highgear 于 2011-5-10 00:05 编辑

结构直接复制 c 语言中使用的不多, 但在 c++ 却是一个热门,几乎每一本书,几乎每一个 c++ 程序员的面试都不可避免的提到结构直接复制的问题。我们现在来探讨结构直接复制在 c c++ 有什么异同,先来看看一段简单的程序:


 
typedef struct SA
{
   char x;
} A;

void main (void) {
    A a1, a2;
    a1 = a2;
}



其中的 a1 = a2, 就是结构直接复制 c 中,这种方法优劣如何呢?来看看Keil C 生成的汇编代码:

 

14:         a1 = a2;
C:0x0D07    7808     MOV      R0,#0x08
C:0x0D09    7C00     MOV      R4,#0x00
C:0x0D0B    7D00     MOV      R5,#0x00
C:0x0D0D    7B00     MOV      R3,#0x00
C:0x0D0F    7A00     MOV      R2,#0x00
C:0x0D11    7909     MOV      R1,#0x09
C:0x0D13    7E00     MOV      R6,#0x00
C:0x0D15    7F01     MOV      R7,#0x01
C:0x0D17    120C2C   LCALL    C?COPY(C:0C2C)

可以看到,仅仅一个字节的复制,竟然使用了大量的代码,效率及其低下。而这段代码与Keil C memcpy 是一模一样的:


 

15:         memcpy(&a1, &a2, sizeof(A));
C:0x0CF3    7808     MOV      R0,#0x08
C:0x0CF5    7C00     MOV      R4,#0x00
C:0x0CF7    7D00     MOV      R5,#0x00
C:0x0CF9    7B00     MOV      R3,#0x00
C:0x0CFB    7A00     MOV      R2,#0x00
C:0x0CFD    7909     MOV      R1,#0x09
C:0x0CFF    7E00     MOV      R6,#0x00
C:0x0D01    7F01     MOV      R7,#0x01
C:0x0D03    120C2C   LCALL    C?COPY(C:0C2C)

这就是说,Keil C 结构直接复制简单的调用了 memcpy 8051 既没有 DMA, 也没有 block move/copy 之类的复制指令,因此 memcpy 的效率不会很高。


现在我们来看看 C++ 下面的表现,编译器使用 Borland C++, 同样的代码,Borland c++ 显然聪明了很多,仅仅生成了两条 8086 汇编指令:
      cs:026D 8A46FC mov   al,[bp-04]
     cs:0270 8846F8  mov   [bp-08],al

非常精简。 这样,没有什么比较性。我们现在稍微修改一下
typedef struct SA
{

char x[3];

} A;

此时,Borland C++ 同样生成了一大堆的代码:

 

#TEST2#13:  a1 = a2;
  cs:026D 8D46FC         lea    ax,[bp-04]
  cs:0270 16             push   ss
  cs:0271 50             push   ax
  cs:0272 8D46F8         lea    ax,[bp-08]
  cs:0275 16             push   ss
  cs:0276 50             push   ax
  cs:0277 B90300         mov    cx,0003
  cs:027A E8D31E         call   N_SCOPY@

我们可以得出一个结论,borland c++
结构直接复制的效率也不过如此。


等等!  结构(类)直接复制在 c++ 里大量的使用,难道没有一个更好的方法来实现么?比如:

a1.x[0] = a2.x[0];

a1.x[1] = a2.x[1];

a1.x[2] = a2.x[2];

或者,程序员只想复制其中一部分的数据,而不是像在 c 下用memcpy 全部复制?C++ 下有什么样的方法可以实现呢?

相关帖子

沙发
highgear|  楼主 | 2011-5-10 01:28 | 只看该作者
本帖最后由 highgear 于 2011-5-10 01:29 编辑

C++与 C 不同的一个地方是,结构(类)可以有成员函数,其中一个重要的部分是 拷贝构造函数。 这个函数顾名思义是利用 copy 来初始化结构(类)。现在加入一个拷贝构造函数到SA结构中,再来看看结果如何 :

typedef struct SA

{


char x[3];


SA(SA& sa) { x[0] = sa.x[0]; } //拷贝构造函数

} A;

void main (void) {

A a2;

      a2.x[0] = 1;

   A a1 = a2;

     a2 = a1;
}
8086汇编代码:
 
#TEST2#19:  A a1 = a2;
  cs:026D 8A46FC         mov    al,[bp-04]
  cs:0270 8846F8         mov    [bp-08],al
#TEST2#20:  a2 = a1;
  cs:0273 8D46FC         lea    ax,[bp-04]
  cs:0276 16             push   ss
  cs:0277 50             push   ax
  cs:0278 8D46F8         lea    ax,[bp-08]
  cs:027B 16             push   ss
  cs:027C 50             push   ax
  cs:027D B90300         mov    cx,0003
  cs:0280 E8C11E         call   N_SCOPY@


我们发现 A a1 = a2 产生了所希望的精简代码, 但 a2 = a1, 却还是臃肿代码。这是怎么回事? 之间的区别是什么?


A a1 = a2, 由于 a1 处于构造阶段,所以会调用 拷贝构造函数 SA(SA& sa)
{ x[0] = sa.x[0]; }
, 而 a2 = a1 则调用了结构(类) 的默认 copy 函数。只要我们重载复制操作, 就可以让 a2 = a1 按照我们的意愿进行复制。


typedef struct SA

{


char x[3];



SA(SA& sa) { x[0] = sa.x[0]; } //拷贝构造函数



void operator=(SA& sa)
{ x[0] = sa.x[0]; }     //复制函数

} A;



此时,再看看 a2 = a1, 也产生了精简的代码。





结论:

1) Keil C 中, 结构直接复制使用了 memcpy 复制结构, 效率低下, 不建议使用。

2) C++ 中, 由于拷贝构造函数以及 = 重载的存在, 可以使用用户自己的复制函数,可以达到很高的效率

3) C++ 中, 要注意 A a1 = a2 与 a1 = a2 之间的不同。

4) C++ 中, 如果没有 拷贝构造函数或者 = 重载的存在, 默认的拷贝函数会被调用。








使用特权

评论回复
板凳
CC2530| | 2011-5-10 06:32 | 只看该作者
本帖最后由 CC2530 于 2011-5-10 11:21 编辑

楼主你的测试代码,定义了两个局部变量,然后在这两个局部变量赋值,
很多编译器,都会被认为是无效代码,最后编译出的代码一条指令都没有。

我稍微改动一下,使用全局变量。

看看其他编译器:
typedef struct SA 
{
   char x;
} A;

A a1, a2;
   
void test (void)
{
    a1 = a2;
}
IAR 8051 7.60:
        RSEG NEAR_CODE:CODE:NOROOT(0)
//   17 void test (void)
test:
//   18 {
        ; Auto size: 0
        ; Saved register size: 0
//   19     a1 = a2;
        MOV     R0,#a2
        MOV     R1,#a1
        MOV     A,#0x1
        LCALL   ?MOVE_LONG8_IDATA_IDATA
//   20 }
        RET
IAR AVR 5.51:
        RSEG CODE:CODE:NOROOT(1)
//   11 void test (void)
test:
//   12 {
//   13     a1 = a2;
        LDS     R16, (a1 + 1)
        STS     a1, R16
//   14 }
        RET
WinAVR 2010:
 
void test (void)
{
    a1 = a2;
  5a: 80 91 01 01  lds r24, 0x0101
  5e: 80 93 00 01  sts 0x0100, r24
}
  62: 08 95        ret

IAR 430 5.20
        RSEG CODE:CODE:REORDER:NOROOT(1)
//   17 void test (void)
test:
//   18 {
//   19     a1 = a2;
        MOV.B   &a2, &a1
//   20 }
        RET
IAR ARM 5.41
 
        SECTION `.text`:CODE:NOROOT(1)
        THUMB
//   21 void test (void)
//   22
//   23 {
//   24
//   25     a1 = a2;
test:
        LDR.N    R0,??DataTable0  ;; a1
        LDR      R1,[R0, #+4]
        STR      R1,[R0, #+0]
//   26
//   27 }
        BX       LR               ;; return
IAR STM8 1.3
 
        SECTION `.near_func.text`:CODE:REORDER:NOROOT(0)
        CODE
//    8 void test (void)
//    9 {
//   10   
//   11     a1 = a2;
test:
        LD        A, L:a2
        LD        L:a1, A
//   12 }
        RET
测试的编译器中,仅仅只有IAR 8051也是调用RAM复制函数,其他编译器都是直接复制。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
highgear + 1
地板
SLEET1986| | 2011-5-10 07:59 | 只看该作者
关注中--

使用特权

评论回复
5
ayb_ice| | 2011-5-10 08:23 | 只看该作者
标准的就是调用内存COPY程序

使用特权

评论回复
6
原野之狼| | 2011-5-10 08:44 | 只看该作者
LZ不但精通C 还精通C++
学习ing...

使用特权

评论回复
7
CC2530| | 2011-5-10 10:46 | 只看该作者
本帖最后由 CC2530 于 2011-5-10 11:05 编辑

c++ 我也来试试:
测试代码改成:
typedef struct SA
{
   char x;
} A;

A a1, a2;

void test1 (void)
{
        a1 = a2;
}

void test2 (void)
{
        A a1, a2;
        a1 = a2;
}
C++Builder 2009
File1.cpp.23: void test1 (void)
00401168 55               push ebp
00401169 8BEC             mov ebp,esp
File1.cpp.25: a1 = a2;
0040116B A075214000       mov al,[$00402175]
00401170 A274214000       mov [$00402174],al
File1.cpp.26: }
00401175 5D               pop ebp
00401176 C3               ret
00401177 90               nop
File1.cpp.28: void test2 (void)
00401178 55               push ebp
00401179 8BEC             mov ebp,esp
0040117B 51               push ecx
File1.cpp.31: a1 = a2;
0040117C 8A45FE           mov al,[ebp-$02]
0040117F 8845FF           mov [ebp-$01],al
File1.cpp.32: }
00401182 59               pop ecx
00401183 5D               pop ebp
00401184 C3               ret
VC 2008
 
void test1 (void)
{
004113B0  push        ebp  
004113B1  mov         ebp,esp
004113B3  sub         esp,0C0h
004113B9  push        ebx  
004113BA  push        esi  
004113BB  push        edi  
004113BC  lea         edi,[ebp-0C0h]
004113C2  mov         ecx,30h
004113C7  mov         eax,0CCCCCCCCh
004113CC  rep stos    dword ptr es:[edi]
a1 = a2;
004113CE  mov         al,byte ptr [a2 (417140h)]
004113D3  mov         byte ptr [a1 (417141h)],al
}
004113D8  pop         edi  
004113D9  pop         esi  
004113DA  pop         ebx  
004113DB  mov         esp,ebp
004113DD  pop         ebp  
004113DE  ret  
void test2 (void)
{
004113F0  push        ebp  
004113F1  mov         ebp,esp
004113F3  sub         esp,0D8h
004113F9  push        ebx  
004113FA  push        esi  
004113FB  push        edi  
004113FC  lea         edi,[ebp-0D8h]
00411402  mov         ecx,36h
00411407  mov         eax,0CCCCCCCCh
0041140C  rep stos    dword ptr es:[edi]
A a1, a2;
a1 = a2;
0041140E  mov         al,byte ptr [a2]
00411411  mov         byte ptr [a1],al
}
00411414  push        edx  
00411415  mov         ecx,ebp
00411417  push        eax  
00411418  lea         edx,[ (41142Ch)]
0041141E  call        @ILT+140(@_RTC_CheckStackVars@8) (411091h)
00411423  pop         eax  
00411424  pop         edx  
00411425  pop         edi  
00411426  pop         esi  
00411427  pop         ebx  
00411428  mov         esp,ebp
0041142A  pop         ebp  
0041142B  ret   
IAR AVR 5.51 C++
 
        RSEG CODE:CODE:NOROOT(1)
//   13 void test1 (void)
??test1:
//   14
//   15 {
//   16
//   17         a1 = a2;
        LDS     R16, (a1 + 1)
        STS     a1, R16
//   18
//   19 }
        RET
//   20
//   21
//   22
        RSEG CODE:CODE:NOROOT(1)
//   23 void test2 (void)
??test2:
//   24
//   25 {
//   26
//   27         A a1, a2;
//   28
//   29         a1 = a2;
//   30
//   31 }
        RET
IAR ARM 5.41 C++
 
        SECTION `.text`:CODE:NOROOT(1)
        THUMB
//   15 void test1 (void)
//   16
//   17 {
//   18
//   19         a1 = a2;
_Z5test1v:
        LDR.N    R0,??DataTable0  ;; a1
        LDR      R1,[R0, #+4]
        STR      R1,[R0, #+0]
//   20
//   21 }
        BX       LR               ;; return
        SECTION `.text`:CODE:NOROOT(2)
        DATA
??DataTable0:
        DC32     a1
//   22
//   23
//   24
        SECTION `.text`:CODE:NOROOT(1)
        THUMB
//   25 void test2 (void)
//   26
//   27 {
//   28
//   29         A a1, a2;
//   30
//   31         a1 = a2;
//   32
//   33 }
_Z5test2v:
        BX       LR               ;; return
IAR 430 5.20 C++
 
        RSEG CODE:CODE:REORDER:NOROOT(1)
//   15 void test1 (void)
??test1:
//   16
//   17 {
//   18
//   19         a1 = a2;
        MOV.B   &a2, &a1
//   20
//   21 }
        RET
//   22
//   23
//   24
        RSEG CODE:CODE:REORDER:NOROOT(1)
//   25 void test2 (void)
??test2:
//   26
//   27 {
//   28
//   29         A a1, a2;
//   30
//   31         a1 = a2;
//   32
//   33 }
        RET


IAR STM8 1.3 C++
 
        SECTION `.near_func.text`:CODE:REORDER:NOROOT(0)
        CODE
//   15 void test1 (void)
//   16
//   17 {
//   18
//   19         a1 = a2;
_Z5test1v:
        LD        A, L:a2
        LD        L:a1, A
//   20
//   21 }
        RET
//   22
//   23
//   24
        SECTION `.near_func.text`:CODE:REORDER:NOROOT(0)
        CODE
//   25 void test2 (void)
//   26
//   27 {
//   28
//   29         A a1, a2;
//   30
//   31         a1 = a2;
//   32
//   33 }
_Z5test2v:
        RET

使用特权

评论回复
8
CC2530| | 2011-5-10 11:08 | 只看该作者
本帖最后由 CC2530 于 2011-5-10 11:21 编辑

WinAVR 2009 C++
000000d8 <_Z5test1v>:

void test1 (void)

{

        a1 = a2;
  d8:        80 91 01 01         lds        r24, 0x0101
  dc:        80 93 00 01         sts        0x0100, r24

}
  e0:        08 95               ret

000000e2 <_Z5test2v>:

        A a1, a2;

        a1 = a2;

}
  e2:        08 95               ret
IAR 8051 7.60 C++
 
        RSEG NEAR_CODE:CODE:NOROOT(0)
//   15 void test1 (void)
??test1:
//   16
//   17 {
        PUSH    DPL
        PUSH    DPH
        ; Saved register size: 2
        ; Auto size: 0
//   18
//   19         a1 = a2;
        MOV     DPTR,#a2
        MOV     R4,#(a1 & 0xff)
        MOV     R5,#((a1 >> 8) & 0xff)
        MOV     A,#0x1
        LCALL   ?MOVE_LONG8_XDATA_XDATA
//   20
//   21 }
        POP     DPH
        POP     DPL
        RET
//   22
//   23
//   24
        RSEG NEAR_CODE:CODE:NOROOT(0)
//   25 void test2 (void)
??test2:
//   26
//   27 {
        ; Saved register size: 0
        ; Auto size: 0
//   28
//   29         A a1, a2;
//   30
//   31         a1 = a2;
//   32
//   33 }
        RET
仅仅只有IAR 8051 C++才调用了RAM复制函数,其他都是直接复制。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
highgear + 1
9
刘前辈| | 2011-5-10 18:48 | 只看该作者
本帖最后由 刘前辈 于 2011-5-10 19:29 编辑

LZ 花时间这个研究值得敬佩。我赞同5楼ayb_ice:标准的就是调用内存COPY程序。C语言大量的库函数就是让用户调用的,C语言教材最形象的说法就是“写C程序就是拎个麻袋,一麻袋C库函数,然后从麻袋里找需要的C模块,来搭建我们希望的建筑。”最好的建筑师才不知道什么水泥砂浆比例,砖头成分,钢筋号……这种事农民工都知道,谁都能做,建筑师关心的是大多数人不知道的事,他是金字塔最上层的人。

    所以,复制一个字节的结构,可以找高中生去写:汇编,C语句都行。而现在要求:复制一个10,000字节的结构或者文件!
    自己写for还是while ?不用,a1=a2; 一分钟不要,很简单就完成了。用不着C++ ,杀**何需宰牛刀?


代码开销:和复制1字节一样。282字节。当然时间可能不一样,C51拷贝什么都是逐字节来的。反正C51上感觉不到,和复制1字节一样快。


使用特权

评论回复
10
刘前辈| | 2011-5-10 19:24 | 只看该作者
本帖最后由 刘前辈 于 2011-5-10 20:02 编辑

多说2句,“比较是在对等的平台上进行的。”86处理器有串拷贝语句,连DMA都不用,就2条汇编内部就完成了。
    那么是不是就可以说:
   “你那C51太差了,应该换86处理器!”(那没有可比性呀。)
    “谁用结构拷贝而不用memcpy( ),赶出论坛。”(玩笑一下,LZ终于自己证明,2者完全一样。终于给我平反了。)
    “结构拷贝从来不是为C准备的……我C+++……”请见《C与指针》P156

看来我第一个用C51,或者franklin C 实现了C++ 功能,能以简代繁,是很得意,看上去很欣赏的一件事。

举个例子,CAN总线模块初始化需要写10个以上功能寄存器,不得不把C像汇编那样一个一个寄存器写,无论中国,外国,学生,教授,什么书上都是这么耐心设置的;仅初始化语句,就要写满一页纸。利用结构拷贝, char arr[]={初始化数据);然后定义好CAN模块功能寄存器区指针,一条赋值语句就完成了。这是从内部RAM 通过总线 向外部Xdata 复制数据。如果说51系列MCU没有DMA,所以效率低下,由此推论刘前辈水平信息太落后,“你怎么不用带DMA的带CAN通信处理器的MCU芯片?”

        呵呵,LZ 知道有这种芯片?  给俺刘前辈推荐一下,重谢。 ( 可别推荐俺拿工控机代替嵌入式MCU,体积太大塞不进去。咱也搬不动。)


、、

使用特权

评论回复
11
cecwxf| | 2011-5-10 21:36 | 只看该作者

使用特权

评论回复
12
highgear|  楼主 | 2011-5-10 21:39 | 只看该作者
特别感谢 CC2530 的补充。
.
.
.
10楼的逻辑能力实在不敢让人恭维。
“我第一个用C51,或者franklin C 实现了C++ 功能", 我家的狗都把牙笑掉了。

技术归技术:
1) “比较是在对等的平台上进行的”, 同样的硬件平台, Borland C++ 对于 a1 = a2 结构直接复制代码效率远远不如 visual C++, Visual C++ 始终可以产生堪比手工的高效代码,不论结构的大小,从1字节到1000字节,这点 cc2530 可以证明。看上去 Keil C 在结构直接复制方面没有做任何优化,比其他同类的编译器也有所不如。因此这不是平台问题,而是编译器的问题,更是程序员的问题。


2)“谁用结构拷贝而不用memcpy( ),赶出论坛。”哈哈,10楼以前恐怕不知道 Keil C 对待结构拷贝就是直接调用 memcpy 吧?在 C 中使用 结构拷贝 等于把控制权交给了编译器, 而使用 memcpy 则由自己掌握,任何一个程序员都不会为一个字节的结构使用 memcpy, 但使用 结构拷贝 却可能因此产生臃肿的代码。

Keil上的一个高手关于结构复制说得在理:
“That's the trade-off: either write it yourself, and know what's going on, or go for convenience and delegate the control to the compiler.
You can't have it both ways, I'm afraid”
这就是交换:要么自己写,你知道会发生什么,要么选择便利而把控制权交给编译器。你不会二者得兼。
.
.
.
二者得兼的问题在C++中得到了很好的解决,可以利用拷贝构造和赋值重载来实现 write it yourself,同时,一些编译器像visual C++, 其默认的结构拷贝所产生的代码效率足够让程序员 go for convenience and delegate the control to the compiler。

这个问题的本质不是在于是否使用结构拷贝,而是在于是否有一种严谨认真的技术态度。

使用特权

评论回复
13
CC2530| | 2011-5-10 22:13 | 只看该作者
还有一个方面需要考虑。

结构体整体赋值,如果结构体比较小。一般编译器会直接把结构体优化到寄存器。
但是,如果对结构体使用memcpy操作,则结构体不能优化到寄存器。

使用特权

评论回复
评分
参与人数 2威望 +2 收起 理由
刘前辈 + 1
highgear + 1
14
highgear|  楼主 | 2011-5-10 22:29 | 只看该作者
同意 13 楼。这一点上,Visual C 做的很好,而Keil C 则不管大小,直接调用 memcpy, 导致结构体整体赋值在Keil C 下的代码效率低下。看 3楼 给出的汇编代码, IAR 也比 Keil C 强不少。

使用特权

评论回复
15
刘前辈| | 2011-5-11 10:40 | 只看该作者
本帖最后由 刘前辈 于 2011-5-11 19:59 编辑

再次提醒所长:“比较是在对等的平台上。”

比Keil C51功能强的C多了,工控机功能比嵌入式MCU强多了,可惜,体积太大,我机顶盒塞不进去。
    所长今年54岁,我30岁,所长年龄功能比俺强不少,岂止不少呀,儿子都快比我年龄功能强了。

送你一张图,除了keil C51,你用什么C都无法给这个环形网上的节点编程。这种环境下:Keil C51是最强的。一览众山小。

    这么简单的道理,54岁的人都不懂?任何东西“存在的,就是合理的。”例如俺30岁,现场总线玩的很转,你所长玩一辈子,行吗?
     ——但是我由此就贬低你。说你54岁白活了,行吗?

     下面看图:1964年,荷兰人.Olof   Soderblom  发明了令牌环形网络,IBM当时以500万美元买断了这项专利。从此,IBM的大型机环形网和 Xeror  的以太网谁优谁劣的争论从未停止……( 其实一样,在各自的应用领域,都有各自最适合的。没有任何一项技术是在所有领域里通吃的!根本无意义的争论。)








、、

使用特权

评论回复
16
刘前辈| | 2011-5-11 11:01 | 只看该作者
所长知道的东西都是大多数人知道的。

多说一句不好听的:你不懂的东西还多呢。

当然我也一样。

使用特权

评论回复
17
gouki_s| | 2011-5-11 12:03 | 只看该作者
这玩意儿的关键,是你需不需要内存中再有一份该结构的拷贝。
如果需要,那就老老实实copy吧,是memcpy还是for区别不大

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
刘前辈 + 1
18
刘前辈| | 2011-5-11 12:42 | 只看该作者
本帖最后由 刘前辈 于 2011-5-11 17:29 编辑

支持LS;只要需要就老老实copy,无论整体赋值还是调用 memcpy 区别不大,甚至完全一样。谁也不会为这一条功能语句的效率问题去换MCU 和 编译器 或者 C++ 。

LZ作为研究可以让我们这些菜鸟开开眼;就是别以否定他人的方式来抬高自己,萝卜白菜,各有所爱。这世界是多元的。你无法强迫别人和你一样观点,这属于典型的“强迫症”症状,劝所长去看看心理医生。真话,我没有恶意。旁观者清,你今年比去年症状明显厉害多了。( 例如,凡事要和别人比较个高下,否则心里就不舒服。最后不惜逻辑混乱,偏要占个上风。——去看看心理学的书,这叫什么心理障碍……书里讲得特清楚。)

     举个例子,您前几天还拿着 memcpy() 说事,大加赞赏,用来压制结构拷贝观点。没过几天,又把自己out了。又来C++了。我知道,再过几天,您一定会用C#说事。您自己有没有觉得不正常?

      13楼分明在说结构复制的优点,你怎么投了赞成票?你不是“谁用结构复制,赶出论坛!”么?立场左右漂移,不知道你到底想说什么,目的是什么。逻辑思维有些混乱,……心理问题?


、、

使用特权

评论回复
19
highgear|  楼主 | 2011-5-11 21:02 | 只看该作者
刘工你的脑袋进水了,还是被门夹过了?

令牌环与结构拷贝有什么关系?刘工你机顶盒塞不进去, 与此帖有什么关系?我既不是你爹,也不是你老师,你的技术难题与我也没有任何关系。刘工你这种行为是不够自信的表现,为非是让人知道刘工你不是水平很差,如此而已。

我想我的帖子把 结构复制 已经说的清清楚楚,明明白白。我的c++程序大量的使用结构复制,我只是不赞成胡乱应用 结构复制, 特别是在 keil c 中,或者比如一个 把一个 memcpy 的函数(https://bbs.21ic.com/icview-233103-1-1.html),用 结构复制来实现。同时,对所谓的“填补空白”“第一”等感到极为可笑。

再者,我不是所长,不能也不打算为所长辩护,所以,也请刘公拿出点男人的气度,尊重无法为自己辩护的所长。如果,刘公下面还是这样,我就会就结构拷贝一道算法题提出公开 PK,只是不知刘公有没有勇气。

使用特权

评论回复
20
highgear|  楼主 | 2011-5-11 21:16 | 只看该作者
17楼:不仅仅如此。
实际上,复制问题是一个相当复杂的问题。结构copy与memcpy 只是简单的“浅复制“,当结构(类)中包含对象指针的时候,浅复制仅仅复制了指针,而不会复制指针所指向的内容,比如字符串。所以在一些编译器提出了一个 clone 说法,即”深复制“。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

1222

帖子

61

粉丝