数组为什么不能进行赋值1

事情都是一个权衡的过程

源代码级别和C语言兼容性的考虑。当年的C++完全向下兼容C;虽然现在标准C和标准C++有相当大的差别,但是表面上的公共语言特性都没有很大改变。

C语言中,数组在许多情况下都会隐式转换为对应的指向数组首个元素的指针(对应的类型转换称为退化)。有了数组的退化特性,同时通过p[i]*(p+i)的等价性就可以以比较方便的语法形式引用数组的元素;且在参数传递时数组退化为指针对一般目的而言是比较高效的,无需按值传递(复制)整个数组。这样做的副作用就是对于operator=而言,为了维护左操作数作为数组名或对应指针名表现的行为的一致性(注意C语言中没有运算符重载,内置运算符的行为对于各种类型而言语义大体一致),数组在这里退化为指针而不表示整个数组。而数组退化得到的指针是常量(指针),因此数组无法作为operator=的左操作数。

理论上要实现数组的内置赋值操作也不复杂,不过应该需要比较严格的类型检查,比如数组类型(元素类型和长度)完全相同或者元素类型相同但左操作数的长度大于等于右操作数的长度,但这样应用很有限,并不是必要的。而且会导致上面的“=”的二义性问题。

实际上用循环对元素进行逐个赋值就可以解决这个问题。C标准库函数memcpy可以实现连续存储器区域按值复制的赋值语义,同样适用于数组(C/C++的数组占据连续的地址空间)。

C++中,可以使用循环或对应的std::memcpy。此外,也可以自行实现成员为数组的结构体/类,然后重载operator[]和operator=实现可用=表示赋值的自定义数组。例如:

template<typename _elementType> class MyArray { private: _elementType* m_array; public: operator=(const _elementType&); //赋值:复制元素的实现可以用std::copy。 operator=(_elementType*); //指针兼容的赋值:考虑内存管理,比较麻烦,不一定需要实现。内置数组是寄存器/自动存储类对象(动态分配得到的是指针不是数组),没有这个问题。 _elementType& operator[](std::size_t); //引用元素。 const _elementType& operator[](std::size_t) const; operator _elementType*(); //退化。 operator const _elementType*() const; };

(当然不支持“=”的设计也有一些缺陷。这样的语言特性导致数组不是first level citizen,除了直观性问题外,还有其它的副作用。例如,多维数组事实上是数组的数组,如果要用循环实现多维数组间部分元素的复制,支持内置“=”的话一个一重循环就够了,编译器可以推断出复制细节;而现在的需要用多重循环“=”,或者使用一重循环嵌套memcpy之类的用于实现复制细节的函数,形式上更麻烦。)

References

  1. 原创回答团百度知道的回答

results matching ""

    No results matching ""