为什么结构内的数组的C ++支持成员逐一分配,但是一般不? [英] Why does C++ support memberwise assignment of arrays within structs, but not generally?

查看:289
本文介绍了为什么结构内的数组的C ++支持成员逐一分配,但是一般不?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的理解是不支持的阵列的成员逐一分配,这样,下面的不会起作用:

I understand that memberwise assignment of arrays is not supported, such that the following will not work:

int num1[3] = {1,2,3};
int num2[3];
num2 = num1; // "error: invalid array assignment"

我刚刚接受了这个事实,因为,盘算,语言的目的是提供一个开放的框架,让用户决定如何实现一些诸如阵列的复制。

I just accepted this as fact, figuring that the aim of the language is to provide an open-ended framework, and let the user decide how to implement something such as the copying of an array.

但是,以下不工作:

struct myStruct {int num[3];};
myStruct struct1={{1,2,3}};
myStruct struct2;
struct2 = struct1;

阵列 NUM [3] 是成员明智的,从它的实例在 struct1 分配到其实例 struct2

The array num[3] is member-wise assigned from its instance in struct1, into its instance in struct2.

为什么支持的阵列成员明智分配的结构,而不是一般的?

Why is member-wise assignment of arrays supported for structs, but not in general?

修改 罗杰·佩特的在线程<评论href=\"http://stackoverflow.com/questions/2009996/stdstring-in-struct-copy-assignment-issues\">std::string在结构 - 复制/分配问题似乎答案的大方向,以点带面,但我不知道够不够,以确认它自己

edit: Roger Pate's comment in the thread std::string in struct - Copy/assignment issues? seems to point in the general direction of the answer, but I don't know enough to confirm it myself.

编辑2 :很多优秀的响应。我选择的路德Blissett 因为我最好奇的是行为背后的哲学或历史的理由,但詹姆斯McNellis 的参照相关规范文件是有用的。

edit 2: Many excellent responses. I choose Luther Blissett's because I was mostly wondering about the philosophical or historical rationale behind the behavior, but James McNellis's reference to the related spec documentation was useful as well.

推荐答案

下面是我对此采取:

c语言的发展的酒店在数组类型在C进化的一些见解:

The Development of the C Language offers some insight in the evolution of the array type in C:

我会尽力勾勒出数组的事情:

I'll try to outline the array thing:

C'S先行者B和BCPL没有明显的数组类型,像一个声明:

C's forerunners B and BCPL had no distinct array type, a declaration like:

auto V[10] (B)
or 
let V = vec 10 (BCPL)

将宣布V至是被初始化为指向10的记忆改为未使用的区域(无类型)指针。乙已经使用 * 为指针引用,并有 [] 简写形式, *( V + I)意味着 V [I] ,就像在C / C ++今天。然而, V 不是一个数组,它仍然是具有指向一些内存的指针。这引起了麻烦,当丹尼斯里奇试图与结构类型扩展B点。他想数组是结构的一部分,类似于C的今天:

would declare V to be a (untyped) pointer which is initialized to point to an unused region of 10 "words" of memory. B already used * for pointer dereferencing and had the [] short hand notation, *(V+i) meant V[i], just as in C/C++ today. However, V is not an array, it is still a pointer which has to point to some memory. This caused trouble when Dennis Ritchie tried to extend B with struct types. He wanted arrays to be part of the structs, like in C today:

struct {
    int inumber;
    char name[14];
};

但与B,数组的指针的BCPL理念,这一切都需要在名称字段包含一个指针,必须是在运行时初始化的到的结构在14个字节的内存区域。初始化/布局问题最终被给予阵列特殊处理解决:编译器将跟踪结构阵列的位置,栈等上,而不实际需要的指针数据实现,除了在离pressions这涉及阵列。这种处理,使几乎所有的B code到仍然可以运行,是的阵列转换如果你看看他们指针的规则的源。这是一个兼容性工具,它被证明是非常方便的,因为它允许打开的大小的数组等。

But with the B,BCPL concept of arrays as pointers, this would have required the name field to contain a pointer which had to be initialized at runtime to a memory region of 14 bytes within the struct. The initialization/layout problem was eventually solved by giving arrays a special treatment: The compiler would track the location of arrays in structures, on the stack etc. without actually requiring the pointer to the data to materialize, except in expressions which involve the arrays. This treatment allowed almost all B code to still run and is the source of the "arrays convert to pointer if you look at them" rule. It is a compatiblity hack, which turned out to be very handy, because it allowed arrays of open size etc.

这是我的猜测,为什么数组不能分配:因为数组是B中三分球,你可以简单地写:

And here's my guess why array can't be assigned: Since arrays were pointers in B, you could simply write:

auto V[10];
V=V+5;

要变基阵列。这是现在意义的,因为数组变量的基础不是一个左值了。因此,这assigment被判无效,这有助于赶上这样做重订基期的上声明数组的为数不多的方案。然后这个概念卡住:作为数组从未被设计成citized C类型系统的第一类,他们大多特殊的野兽,如果你使用它们这成为指针处理。而且从一定的角度(这忽略了C-阵列是一个拙劣的黑客),不允许数组赋值仍然有一定的道理:一个开放数组或数组函数参数将被视为无大小信息的指针。编译器不具备的信息来为他们生成数组赋值,所以需要出于兼容性考虑指针赋值。对于声明数组介绍数组赋值会引入错误,虽然杂散assigments(是= BA指针赋值或按元素的副本?)和其他麻烦(你怎么按值传递数组?)没有实际解决一个问题 - 只要让一切明确与memcpy的!

to rebase an "array". This was now meaningless, because the base of an array variable was not a lvalue anymore. So this assigment was disallowed, which helped to catch the few programs that did this rebasing on declared arrays. And then this notion stuck: As arrays were never designed to be first class citized of the C type system, they were mostly treated as special beasts which become pointer if you use them. And from a certain point of view (which ignores that C-arrays are a botched hack), disallowing array assignment still makes some sense: An open array or an array function parameter is treated as a pointer without size information. The compiler doesn't have the information to generate an array assignment for them and the pointer assignment was required for compatibility reasons. Introducing array assignment for the declared arrays would have introduced bugs though spurious assigments (is a=b a pointer assignment or an elementwise copy?) and other trouble (how do you pass an array by value?) without actually solving a problem - just make everything explicit with memcpy!

/* Example how array assignment void make things even weirder in C/C++, 
   if we don't want to break existing code.
   It's actually better to leave things as they are...
*/
typedef int vec[3];

void f(vec a, vec b) 
{
    vec x,y; 
    a=b; // pointer assignment
    x=y; // NEW! element-wise assignment
    a=x; // pointer assignment
    x=a; // NEW! element-wise assignment
}

这并没有改变,当C在1978年某个版本增加结构分配(<一个href=\"http://cm.bell-labs.com/cm/cs/who/dmr/cchanges.pdf\">http://cm.bell-labs.com/cm/cs/who/dmr/cchanges.pdf )。虽然记录的的不同类型C,这是不可能给它们分配在早期K&安培; R C.你必须将它们复制成员明智的memcpy和你可以只传递指针把它们称为功能参数。 Assigment(和参数传递),现在被简单地定义为结构的原始记忆的memcpy和因为这个℃下将其容易adpoted无法突破exsisting $ C $。作为一个意想不到的副作用,这隐含地引入某种阵列分配的,但这种happended一个结构内的某个地方,所以这不能真正引入随路芯片被用来问题。

This didn't change when a revision of C in 1978 added struct assignment ( http://cm.bell-labs.com/cm/cs/who/dmr/cchanges.pdf ). Even though records were distinct types in C, it was not possible to assign them in early K&R C. You had to copy them member-wise with memcpy and you could pass only pointers to them as function parameters. Assigment (and parameter passing) was now simply defined as the memcpy of the struct's raw memory and since this couldn't break exsisting code it was readily adpoted. As a unintended side effect, this implicitly introduced some kind of array assignment, but this happended somewhere inside a structure, so this couldn't really introduce problems with the way arrays were used.

这篇关于为什么结构内的数组的C ++支持成员逐一分配,但是一般不?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆