C++ 为什么引用数组是非法的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1164266/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:05:15  来源:igfitidea点击:

Why are arrays of references illegal?

c++arraysreference

提问by Alexey Malistov

The following code does not compile.

以下代码无法编译。

int a = 1, b = 2, c = 3;
int& arr[] = {a,b,c,8};

What does the C++ standard say about this?

C++ 标准对此有何看法?

I know I could declare a class that contains a reference, then create an array of that class, as shown below. But I really want to know why the code above doesn't compile.

我知道我可以声明一个包含引用的类,然后创建该类的数组,如下所示。但我真的很想知道为什么上面的代码不能编译。

struct cintref
{
    cintref(const int & ref) : ref(ref) {}
    operator const int &() { return ref; }
private:
    const int & ref;
    void operator=(const cintref &);
};

int main() 
{
  int a=1,b=2,c=3;
  //typedef const int &  cintref;
  cintref arr[] = {a,b,c,8};
}

It is possible to use struct cintrefinstead of const int &to simulate an array of references.

可以使用struct cintref代替const int &来模拟引用数组。

回答by Kirill V. Lyadvinsky

Answering to your question about standard I can cite the C++ Standard §8.3.2/4:

回答您关于标准的问题,我可以引用C++ 标准 §8.3.2/4

There shall be no references to references, no arrays of references, and no pointers to references.

不应有对引用的引用,没有引用数组,也没有指向引用的指针。

回答by CB Bailey

References are not objects. They don't have storage of their own, they just reference existing objects. For this reason it doesn't make sense to have arrays of references.

引用不是对象。他们没有自己的存储,他们只是引用现有的对象。出于这个原因,拥有引用数组是没有意义的。

If you want a light-weight objectthat references another object then you can use a pointer. You will only be able to use a structwith a reference member as objects in arrays if you provide explicit initialization for all the reference members for all structinstances. References cannot be default initalized.

如果你想要一个引用另一个对象的轻量级对象,那么你可以使用指针。struct如果您为所有struct实例的所有引用成员提供显式初始化,您将只能将 a与引用成员一起用作数组中的对象。引用不能默认初始化。

Edit:As jia3ep notes, in the standard section on declarations there is an explicit prohibition on arrays of references.

编辑:正如 jia3ep 所指出的,在声明的标准部分中,明确禁止引用数组。

回答by greggo

This is an interesting discussion. Clearly arrays of refs are outright illegal, but IMHO the reason why is not so simple as saying 'they are not objects' or 'they have no size'. I'd point out that arrays themselves are not full-fledged objects in C/C++ - if you object to that, try instantiating some stl template classes using an array as a 'class' template parameter, and see what happens. You can't return them, assign them, pass them as parameters. ( an array param is treated as a pointer). But it is legal to make arrays of arrays. References do have a size that the compiler can and must calculate - you can't sizeof() a reference, but you can make a struct containing nothing but references. It will have a size sufficient to contain all the pointers which implement the references. You can't instantiate such a struct without initializing all the members:

这是一个有趣的讨论。显然,引用数组是完全非法的,但恕我直言,原因不是说“它们不是对象”或“它们没有大小”那么简单。我要指出的是,数组本身并不是 C/C++ 中的成熟对象——如果您反对这一点,请尝试使用数组作为“类”模板参数来实例化一些 stl 模板类,然后看看会发生什么。你不能返回它们,分配它们,将它们作为参数传递。(数组参数被视为指针)。但是制作数组数组是合法的。引用确实具有编译器可以并且必须计算的大小 - 您不能使用 sizeof() 引用,但是您可以创建一个只包含引用的结构。它将有足够的大小来包含实现引用的所有指针。你可以'

struct mys {
 int & a;
 int & b;
 int & c;
};
...
int ivar1, ivar2, arr[200];
mys my_refs = { ivar1, ivar2, arr[12] };

my_refs.a += 3  ;  // add 3 to ivar1

In fact you can add this line to the struct definition

实际上,您可以将此行添加到结构定义中

struct mys {
 ...
 int & operator[]( int i ) { return i==0?a : i==1? b : c; }
};

...and now I have something which looks a LOT like an array of refs:

...现在我有一些看起来很像一组参考的东西:

int ivar1, ivar2, arr[200];
mys my_refs = { ivar1, ivar2, arr[12] };

my_refs[1] = my_refs[2]  ;  // copy arr[12] to ivar2
&my_refs[0];               // gives &my_refs.a == &ivar1

Now, this is not a real array, it's an operator overload; it won't do things that arrays normally do like sizeof(arr)/sizeof(arr[0]), for instance. But it does exactly what I want an array of references to do, with perfectly legal C++. Except (a) it's a pain to set up for more than 3 or 4 elements, and (b) it's doing a calculation using a bunch of ?: which could be done using indexing (not with normal C-pointer-calculation-semantics indexing, but indexing nonetheless). I'd like to see a very limited 'array of reference' type which can actually do this. I.e. an array of references would not be treated as a general array of things which are references, but rather it would be a new 'array-of-reference' thing which effectively maps to an internally generated class similar to the one above (but which you unfortunately can'tmake with templates).

现在,这不是一个真正的数组,它是一个运算符重载;例如,它不会做数组通常做的事情,比如 sizeof(arr)/sizeof(arr[0])。但它正是我想要的引用数组做的事情,使用完全合法的 C++。除了 (a) 设置超过 3 或 4 个元素很痛苦,并且 (b) 它正在使用一堆 ?: 进行计算,这可以使用索引来完成(而不是使用普通的 C-pointer-calculation-semantics 索引,但仍然索引)。我想看到一个非常有限的“引用数组”类型,它实际上可以做到这一点。即引用数组不会被视为引用的一般数组,而是一个新的“引用数组”用模板制作)。

this would probably work, if you don't mind this kind of nasty: recast '*this' as an array of int *'s and return a reference made from one: (not recommended, but it shows how the proper 'array' would work):

如果您不介意这种讨厌的事情,这可能会奏效:将 '*this' 重铸为 int *'s 的数组并返回一个引用:(不推荐,但它显示了正确的 'array'会工作):

 int & operator[]( int i ) { return *(reinterpret_cast<int**>(this)[i]); }

回答by Youw

Comment to your edit:

评论您的编辑:

Better solution is std::reference_wrapper.

更好的解决方案是std::reference_wrapper

Details: http://www.cplusplus.com/reference/functional/reference_wrapper/

详情:http: //www.cplusplus.com/reference/functional/reference_wrapper/

Example:

例子:

#include <iostream>
#include <functional>
using namespace std;

int main() {
    int a=1,b=2,c=3,d=4;
    using intlink = std::reference_wrapper<int>;
    intlink arr[] = {a,b,c,d};
    return 0;
}

回答by EFraim

An array is implicitly convertable to a pointer, and pointer-to-reference is illegal in C++

数组可隐式转换为指针,C++ 中的指针指向引用是非法的

回答by PaulMurrayCbr

Given int& arr[] = {a,b,c,8};, what is sizeof(*arr)?

鉴于int& arr[] = {a,b,c,8};,什么是sizeof(*arr)

Everywhere else, a reference is treated as being simply the thing itself, so sizeof(*arr)should simply be sizeof(int). But this would make array pointer arithmetic on this array wrong (assuming that references are not the same widths is ints). To eliminate the ambiguity, it's forbidden.

在其他任何地方,引用都被视为简单的事物本身,因此sizeof(*arr)应该只是sizeof(int). 但这会使该数组上的数组指针算术错误(假设引用的宽度不同,则为整数)。为了消除歧义,这是被禁止的。

回答by navigator

Because like many have said here, references are not objects. they are simply aliases. True some compilers might implement them as pointers, but the standard does not force/specify that. And because references are not objects, you cannot point to them. Storing elements in an array means there is some kind of index address (i.e., pointing to elements at a certain index); and that is why you cannot have arrays of references, because you cannot point to them.

因为就像很多人在这里所说的那样,引用不是对象。它们只是别名。确实,某些编译器可能会将它们实现为指针,但标准并未强制/指定。因为引用不是对象,所以你不能指向它们。在数组中存储元素意味着存在某种索引地址(即指向某个索引处的元素);这就是为什么你不能拥有引用数组的原因,因为你不能指向它们。

Use boost::reference_wrapper, or boost::tuple instead; or just pointers.

使用 boost::reference_wrapper 或 boost::tuple 代替;或只是指针。

回答by Kristupas A.

I believe the answer is very simple and it has to do with semantic rules of references and how arrays are handled in C++.

我相信答案非常简单,它与引用的语义规则以及在 C++ 中如何处理数组有关。

In short: References can be thought of as structs which don't have a default constructor, so all the same rules apply.

简而言之:引用可以被认为是没有默认构造函数的结构,因此所有相同的规则都适用。

1) Semantically, references don't have a default value. References can only be created by referencing something. References don't have a value to represent the absence of a reference.

1) 从语义上讲,引用没有默认值。引用只能通过引用某些东西来创建。引用没有表示没有引用的值。

2) When allocating an array of size X, program creates a collection of default-initialized objects. Since reference doesn't have a default value, creating such an array is semantically illegal.

2) 当分配一个大小为 X 的数组时,程序会创建一个默认初始化对象的集合。由于引用没有默认值,创建这样的数组在语义上是非法的。

This rule also applies to structs/classes which don't have a default constructor. The following code sample doesn't compile:

此规则也适用于没有默认构造函数的结构/类。以下代码示例无法编译:

struct Object
{
    Object(int value) { }
};

Object objects[1]; // Error: no appropriate default constructor available

回答by greggo

You can get fairly close with this template struct. However, you need to initialize with expressions that are pointers to T, rather than T; and so, though you can easily make a 'fake_constref_array' similarly, you won't be able to bind that to rvalues as done in the OP's example ('8');

你可以相当接近这个模板结构。但是,您需要使用指向 T 而不是 T 的指针的表达式进行初始化;因此,尽管您可以类似地轻松制作 'fake_constref_array',但您将无法像 OP 的示例 ('8') 中那样将其绑定到右值;

#include <stdio.h>

template<class T, int N> 
struct fake_ref_array {
   T * ptrs[N];
  T & operator [] ( int i ){ return *ptrs[i]; }
};

int A,B,X[3];

void func( int j, int k)
{
  fake_ref_array<int,3> refarr = { &A, &B, &X[1] };
  refarr[j] = k;  // :-) 
   // You could probably make the following work using an overload of + that returns
   // a proxy that overloads *. Still not a real array though, so it would just be
   // stunt programming at that point.
   // *(refarr + j) = k  
}

int
main()
{
    func(1,7);  //B = 7
    func(2,8);     // X[1] = 8
    printf("A=%d B=%d X = {%d,%d,%d}\n", A,B,X[0],X[1],X[2]);
        return 0;
}

--> A=0 B=7 X = {0,8,0}

--> A=0 B=7 X = {0,8,0}

回答by Pradyot

When you store something in an array , its size needs to be known (since array indexing relies on the size). Per the C++ standard It is unspecified whether or not a reference requires storage, as a result indexing an array of references would not be possible.

当你在一个数组中存储一些东西时,它的大小需要知道(因为数组索引依赖于大小)。根据 C++ 标准 未指定引用是否需要存储,因此无法对引用数组进行索引。