2010-10-22 51 views
5

OK。我们知道以下代码无法编译。在赋值运算符函数中,隐式数组是memcpy

char source[1024]; 
char dest[1024]; 
// Fail. Use memcpy(dest, source, sizeof(source)); instead. 
dest = source; 

但是,下面的代码可以被编译并且行为正确。

class A { 
    char data[1024]; 
}; 
A source; 
B dest; 
dest = source; 

我想知道,在运算符赋值函数中,数组是隐式的吗?

以下是完整的测试代码。


#include <cstdio> 
#include <memory> 

class A { 
public: 
    char data[1024]; 
}; 

int main() { 
    { 
     A source; 
     A dest; 

     // Initialization 
     char *data = "hello world"; 
     memcpy (source.data, data, strlen(data) + 1); 

     printf ("source.data = %s\n", source.data); 
     printf ("address source.data = %x\n", source.data); 

     // Works! Does this in the operator assignment function, memcpy is 
     // being performed implicitly on array. 
     dest = source; 

     printf ("dest.data = %s\n", dest.data); 
     printf ("address dest.data = %x\n", dest.data); 
    } 

    { 
     char source[1024]; 
     char dest[1024]; 

     // Initialization 
     char *data = "hello world"; 
     memcpy (source, data, strlen(data) + 1); 

     printf ("source = %s\n", source); 
     printf ("address source = %x\n", source); 

     // '=' : left operand must be l-value 
     // dest = source; 
     // Works with memcpy. 
     memcpy(dest, source, sizeof(source)); 

     printf ("dest = %s\n", dest); 
     printf ("address dest = %x\n", dest); 
    } 

    getchar(); 
} 

//RESULT : 
//source.data = hello world 
//address source.data = 12fb60 
//dest.data = hello world 
//address dest.data = 12f758 
//source = hello world 
//address source = 12f344 
//dest = hello world 
//address dest = 12ef3c 
+0

关于[为什么C++支持结构中的成员数组赋值,但通常不是?](http://stackoverflow.com/questions/3437110/why-does -c-support-memberwise-arrays-arrays-within-structs-but-not-gene) – 2010-10-22 02:55:44

+0

反对std :: string,是吗? – 2010-10-22 04:02:50

回答

2

编译器生成的复制构造函数/分配-op是逐位拷贝,如果找到符合的子元素没有复制构造函数/赋值运算。

编辑
这是修改后的测试用例,显示了这个概念。

#include <cstdio> 
#include <memory> 

class someElement 
{ 
public: 
    someElement() : theData(0) {} 
    // Intentionally copy-edit 
    someElement(const someElement& src) : theData(src.theData + 1) {} 
    ~someElement(){} 

    someElement& operator=(const someElement& rhs) 
    { 
     theData = rhs.theData - 1; 
     return *this; 
    } 

    char theData; 
}; 

class A { 
public: 
    someElement data[1024]; 
}; 

int main() { 
    { 
     A source; 
     A dest; 

     // Initialization 
     char *data = "hello world"; 
     memcpy (source.data, data, strlen(data) + 1); 

     printf ("source.data = %s\n", source.data); 
     printf ("address source.data = %x\n", source.data); 

     // Works! Does this in the operator assignment function, memcpy is 
     // being performed implicitly on array. 
     dest = source; 

     printf ("dest.data = %s\n", dest.data); 
     printf ("address dest.data = %x\n", dest.data); 
    } 

    { 
     someElement source[1024]; 
     someElement dest[1024]; 

     // Initialization 
     char *data = "hello world"; 
     memcpy (source, data, strlen(data) + 1); 

     printf ("source = %s\n", source); 
     printf ("address source = %x\n", source); 

     // '=' : left operand must be l-value 
     // dest = source; 
     // Works with memcpy. 
     memcpy(dest, source, sizeof(source)); 

     printf ("dest = %s\n", dest); 
     printf ("address dest = %x\n", dest); 
    } 

    getchar(); 
} 
+0

如何在阵列上执行按位复制?任何参考源? – 2010-10-22 02:53:13

+0

@Yan Cheng CHEOK:对每个元素轮流调用operator =。这是一种递归 – Chubsdad 2010-10-22 02:55:46

4

operator=,如果没有明确落实,执行的类的内容的成员复制。对于你的封装数组,这将起作用,但是通常需要注意确保对类的数据进行适当的深层复制。

+0

请注意,如果成员具有assignment-op,它不是按位复制。 – YeenFei 2010-10-22 02:58:38

+2

否。它执行成员智能副本。这是必要的,因为嵌套类型可能在嵌套层次结构的任意深度都有自己的operator =()。他们的operator =()可能会在位拷贝会影响的位范围之外产生任何数量的副作用。这些副作用保证发生。所以,不,副本不是按位。 – 2010-10-22 04:02:07

+0

@Eric - 谢谢,更新了文字和upvoted备用答案 – 2010-10-22 10:23:59

9

标准的这句话有帮助吗?这是安静的自我解释

对不起,删除我以前的答案是有关复制构造函数,而不是复制赋值运算符。

$ 12.8/30-

的隐式定义的拷贝赋值运算符 对非工会类X 执行按成员拷贝的 其子对象的分配。直接基 类X首先被分配,在 其声明中 基本符列表的顺序,然后X 的 直接非静态数据成员被分配在顺序 他们在类别 定义中声明。 - ;即,忽略任何如果子对象是类的类型, 为 类的拷贝赋值运算符被使用(如,如果通过显式 资格

:每个子对象以适合其种类的方式分配 更多派生类中可能的虚拟覆盖函数 );

- 如果 子对象是一个数组,每一个元素是 分配,以适合于 元素类型的方式;

- 如果子对象 是标量类型,则使用内置的 赋值运算符。