C 数组元素为什么不可以是引用?说出最说服力的原因……

时间:2008-05-30 09:28:02   来源:论坛整理  作者:  编辑:chinaitzhe
int i, j;
int & arr[] = {i, j};

//use arr...
网友回复:呃,在那个编译器上能通过?
网友回复:晕,你的类型好歹也要匹配啊!
这种用法绝对错误.
网友回复:我类型怎末不匹配了……
网友回复:1. 各个编译器都没有实现这样的语法

2. 编译器实现的难度较大, 实现数组的引用, 有可能出现栈空间的数组引用堆空间的元素, 或堆空间的数组引用栈空间的元素, 各变量元素的生存期处理将会很混乱

3. C/C 中数组的优势在于一片连续的内存空间. 亦即具有O(1)的随机存取特性, 支持数组元素引用后, 内存空间将不具有连续性. C/C 中数组与指针紧密联系, 由于内存空间的连续性, 则可以对a[2], 采用 int *p = &(a[0]), *(p 2)的方式去存取a[2], 支持数组引用势必对这种语法的一种挑战, 要么就是扩展指针的 /-运算的逻辑

4. LZ所指的数组引用功能可以由指针数组方式折衷实现,
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





int i,j;

int *a[5] = {&i, &j};

a[0]; // point to i

a[1]; // point to j





网友回复:
引用 4 楼 xiaocai0001 的回复:
1. 各个编译器都没有实现这样的语法

2. 编译器实现的难度较大, 实现数组的引用, 有可能出现栈空间的数组引用堆空间的元素, 或堆空间的数组引用栈空间的元素, 各变量元素的生存期处理将会很混乱

3. C/C 中数组的优势在于一片连续的内存空间. 亦即具有O(1)的随机存取特性, 支持数组元素引用后, 内存空间将不具有连续性. C/C 中数组与指针紧密联系, 由于内存空间的连续性, 则可以对a[2], 采用 int *p = &(a[0]), *(p 2)的…


2. 引用本来就用指针实现,你说的那些本来就可能出现这看程序员,为什么编译器支持指针不支持引用成组
3. 没什么挑战,同上用指针实现
4. 好~
网友回复:实际上C 引用是可以作为数组元素存放的, 只不过你用错了
引用实际上是一种别名机制,所以对于引用而言,它的类型就是原引用变量的类型,
如:
int i;
int & ref = i; // 实际上引用ref的类型就是int类型
这样的话, 假如数组元素是引用的话, 整个数据定义的类型就应该是原引用变量的类型。
下面这段程序在gcc 3.4.4中测试通过:
#include <stdio.h>
int main()
{
int i,j;
int & ref1 = i;
int & ref2 = j;
int ref[] = {ref1, ref2}; // 注重:数组定义的类型是原引用变量的类型
ref[0] = 1;
ref[1] = 2;
printf("ref[0]=%d\n", ref[0]);
printf("ref[1] = %d\n", ref[1]);
return 0;
}

网友回复:
引用 6 楼 fjpqzm 的回复:
下面这段程序在gcc 3.4.4中测试通过:
#include <stdio.h>
int main()
{
int i,j;
int & ref1 = i;
int & ref2 = j;
int ref[] = {ref1, ref2}; // 注重:数组定义的类型是原引用变量的类型
ref[0] = 1;
ref[1] = 2;
printf("ref[0]=%d\n", ref[0]);
printf("ref[1] = %d\n", ref[1]);
return 0;
}


这不是我的愿意。
你这个ref[]是从ref1和ref2拷贝了两个整数到数组,ref[0] = 1仍然不能改变i的值


网友回复:
引用 5 楼 Paradin 的回复:
2. 引用本来就用指针实现,你说的那些本来就可能出现这看程序员,为什么编译器支持指针不支持引用成组
3. 没什么挑战,同上用指针实现
4. 好~

引用具体怎么实现, 那是编译器的事情, 只不过现代的编译器大部分会处理成常指针形式. 但不排除用其它方式去实现.

另外你说的这个特性, 并不说不能实现, 不过对编译器支持哪些特性, 不支持哪些特性, 一方面需要从C 语法本身来考虑, 另一方面也要从特性本身的价值及实现难度来考虑.

就拿VC6.0实现的C 编译器cl, 与标准相比, 它实现了C 标准的一部分,不是标准里的全部特性都支持, 同时它也扩展了一部分, 这部分是C 标准里所没有的特性.

假如有可能, 你也可以在开源的一些Compiler上去实现这个引用数组的功能.

我第一帖说的意思就是: 需不需要加入某一feature,主要是从正反两方面去看, 一是它带来的好处, 简化编程还是其他的, 另一方面就是看实现难度等问题.
网友回复:学习
网友回复:的确如此,我不是死扣不能实现这一点。我发贴问的就是为什么编译器都选择不去实现这个特点的原因,顾虑的因素有哪些。总得有些个具体的方面吧。我想到一个就是对代码的可读性有很大影响,究竟人们都习惯了数组直接存放对象或指针,但这种习惯是不是因为编译器一开始就没有考虑引用呢,因果……
网友回复:
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





#include <iostream>



using namespace std;



int main()

{

    int a[10]={1,2,3,4};

    int (&x)[10]=a;

    for(size_t index=0;index!=sizeof(a)/sizeof(a[0]);  index)

        cout<<*x index<<" ";

    return 0;

}






网友回复:因为你说的这个已经偏离了数组本身很原始的含义了.
数组的特点就是在内存中的一块连续区域.
可以用数组首地址加上偏移量就可以直接定位到所取元素,且各元素地址之间具有简单的加减关系.

加上引用数组后则破坏这种特性, 诚然可以用指针数组做为内部实现机制, 但借助指针的实现, 则在汇编层次上说就是一个间接寻址的过程了.

引用 10 楼 Paradin 的回复:
的确如此,我不是死扣不能实现这一点。我发贴问的就是为什么编译器都选择不去实现这个特点的原因,顾虑的因素有哪些。总得有些个具体的方面吧。我想到一个就是对代码的可读性有很大影响,究竟人们都习惯了数组直接存放对象或指针,但这种习惯是不是因为编译器一开始就没有考虑引用呢,因果……


网友回复:11楼那个是对整个数组引用

xiaocai0001是说假如可以把引用放到数组里,那么引用变量就可以被程序员寻地址了

int i, j;
int& arr[] = {i, j}

arr i 就是第i个引用的地址了,这确实破坏了C 设计引用的初衷,我完全把引用和常指针等同起来是不对的~
网友回复:o
网友回复:This computer have no Chinese IME installed,
so I am using Chenglish. :)

I think a compiler can not do that because it does not know
how much memory should be given to a array of refs.

See this example:
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





class C 

{

  double m_d; // or any thing else;

};



C c;

C c2;

C & rc = c;



assert( sizeof(rc) == sizeof(c) ); // this is true !!!



// the following is wrong, 

// C & rcArr[] = {rc, c2};

// if it was right, then think : sizeof(rcArr) == ?;  



// normally, sizeof(rcArr) == 2 * sizeof(C); 



// but, if there are 2 C objects in the array,

// then they would not be refs (names), but normal objects?

// so sizeof(rcArr) != 2*sizeof(C); ant it's not C   rule.



// whether sizeof(rcArr) == 2*sizeof(C) or not, it's wrong.

// so array of refs are not allowed.



//write a class yourself, you can do that;

//I think it's something like this:



template <class C, int N>

class RefArr

{

  C *m_p[N]; // holds pointers. ref to : *m_p[0], *m_p[1], ...

public:

  RefArr(C ** p); // ref to : **p, *(1   *p), *(n   *p)

  C & operator [] (int n) {

    if (n >= 0 && n < N)

       return *m_p[n];

    throw("error");// or sth else.

  }

};








网友回复:楼上的chao_83感觉说的有理哦
网友回复:I think it's not a big problem as when you declare array of reference, your reference type is the same, so it should have the same size.

I agree with 12 floor. An array normally has a continuous memory block. If we allow reference, we cannot have such assumption any more.

What I want to stress is "there isn't always a reason for every why". It's only a rule enforced by C standard. If the C standard allows you to define the reference of array, 12F will not be a problem too.

引用 15 楼 chao_83 的回复:
This computer have no Chinese IME installed,
so I am using Chenglish. :)

I think a compiler can not do that because it does not know
how much memory should be given to a array of refs.

See this example:

C/C code
class C
{
double m_d; // or any thing else;
};

C c;
C c2;
C & rc = c;

assert( sizeof(rc) == sizeof(c) ); // this is true !!!

// the following is wro…

网友回复:简而言之,12楼说的最貌似一个合理的原因。但是要说这一定能说服所有人,则不一定。

原因很简单,不是所有东西都有可信服的原因的。这只是C++语言的一个规定而已,可能是当时的写标准的人基于已经实现的东西达成的一个妥协,也许当时没有几个人认为“引用的数组”很有必要(我现在都认为无必要)。为什么需要把一个没什么大用处的东西加入标准了来增加编译器的复杂度呢?

所以,世界是不完美的,不是所有的东西都有“合理的原因”

网友回复:yes, this could also be a problem.
LargeObj i, j;
LargeObj& arr[] = {i, j}

since sizeof(LargeObj) == sizeof(LargeObj&), why should sizeof(arr) be merely the sizeof 8.

Points are becoming clearer and clearer~

网友回复:
引用 13 楼 Paradin 的回复:
11楼那个是对整个数组引用

xiaocai0001是说假如可以把引用放到数组里,那么引用变量就可以被程序员寻地址了

int i, j;
int& arr[] = {i, j}

arr i 就是第i个引用的地址了,这确实破坏了C 设计引用的初衷,我完全把引用和常指针等同起来是不对的~

注重常指针和指针常量的区别。

常指针是常量的指针。它是指向一个常量的指针,加了该要害字后,不能通过间访操作改变指针指向的值。下面的代码不能通过 *b 给 a 赋值,但是 a 本身是能够赋值的。
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/



int a = 1;           //a 不一定非得定义为常量

const int* b = &a;               //这里 const 修饰 int ,说明 b 的类型是一个常量的指针

*b = 2;                          //加上了 const 要害字后,就不能通过访问 *b 改变 a 的值

a = 2;                           //b 不是常量,可以赋值



而指针常量则是指针类型的常量。它是说指针本身是个常量,亦即当指针初始化后,其指向的地址就不能被改变。
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/



int a1 = 1;

int a2 = 2;

int* const b = &a1;        //指针常量,这里 const 修饰 b ,说明 b 是一个常量

int const* c = &a1;        //两种方式是一个意思,这里 const 修饰 * ,说明 b 的类型是指针常量

int& d = a1;               //d 是 a1的引用,即 a1 的别名

b = &a2;                   //由于 b 是常量,给 b 赋值是不恰当的

*b = 3;                    //可以通过 *b 给 a1 赋值

cout << "d 的地址为: " << &d << endl;  //留意这个地址

d = a2;                    //这里并非让 d 指向 a2,而是将 a2 的值赋给了 a1

cout << "d 的地址为: " << &d << endl;  //d 的地址并未改变

cout << "a1 = " << a1 << endl;        //a1 的值变为 2 了



所以实际上引用完全不能等同于常指针,倒是可以等同于指针常量
网友回复:And when you change an element in a array,
you are changing sth inside the array, not sth else.
but refs are actually sth NOT here.



网友回复:15楼的的解释不成立:
理由:
标准:
8.3.2.3 It is unspecified whether or not a reference requires storage(3.7)

没有引用构成的数组的理由:
标准:
8.3.2.4 There shall be no references to references, no arrys of references, and no pointer to references.

no references to references
这条标准可能会被修改...(我看的是98版的,不知道03版里怎么说的)
网友回复:Again, I'm using Chenglish because
this PC has no Chinese input method.
You can just reply to me in Chinese.
And I understand Chinese better than English. :)
网友回复:Good, thank you. I did not known that rule before.

Since there is a rule,
then what I said might be a guess of why there is such a rule.

引用 22 楼 baihacker 的回复:
15楼的的解释不成立:
理由:
标准:
8.3.2.3?It?is?unspecified?whether?or?not?a?reference?requires?storage(3.7)

没有引用构成的数组的理由:
标准:
8.3.2.4?There?shall?be?no?references?to?references,?no?arrys?of?references,?and?no?pointer?to?references.

no?references?to?references
这条标准可能会被修改...(我看的是98版的,不知道03版里怎么说的)

网友回复:
引用 22 楼 baihacker 的回复:
15楼的的解释不成立:
理由:
标准:
8.3.2.3 It is unspecified whether or not a reference requires storage(3.7)

没有引用构成的数组的理由:
标准:
8.3.2.4 There shall be no references to references, no arrys of references, and no pointer to references.

no references to references
这条标准可能会被修改...(我看的是98版的,不知道03版里怎么说的)


为什么会被修改
网友回复:It should not be a problem too.

档我们说sizeof(ref)=sizeof(obj)时,原因是当你计算sizeof(ref)时,系统会去计算他实际ref的变量,也就是sizeof(ref)会被翻译成sizeof(obj)
假如不是语法标准规定不得定义引用的数组的话,假如你这个sizeof(ref)==sizeof(array)时个合理的要求的话,编译器完全可以翻译sizeof(arrReference) 到sizeof(arrReference[i])的和,这没有啥解决不了的。

所以:楼主的困难在于他假定所有的存在都有一个合理的理由。而事实是由于历史的原因,这个假设不一定成立。规则就是规则,不一定有原因。就似乎说为什么我们用new Type来创建实例,而不用create Type来创建一样。

引用 19 楼 Paradin 的回复:
yes, this could also be a problem.
LargeObj i, j;
LargeObj& arr[] = {i, j}

since sizeof(LargeObj) == sizeof(LargeObj&), why should sizeof(arr) be merely the sizeof 8.

Points are becoming clearer and clearer~

网友回复:8.3.2.4 There shall be no references to references, no arrys of references, and no pointer to references.

恩,标准就是标准,很一致。
假如有引用的数组,那么就承认有指向引用的指针了。
网友回复:额,15楼也是有理由的
貌似
8.3.2.3 It is unspecified whether or not a reference requires storage(3.7)
和15楼的
how much memory should be given to a array of refs
刚好对应
在22楼说

15解释不成立:

是因为
how much memory should be given to a array of refs.
貌似有在说为引用分配内存的嫌疑,而这是unspecified的,所以一开始给了解释不成立的说法.
但是直接给解释不成立也太武断了.

仔细想想,引用需要内存吗?
构造数组的时候呢?

这正是15楼所考虑的,所以可能改成
the storage of the array of refs leads to this problem
貌似要恰当些.

关于这个问题
3.9.2中说明引用是一个compound type也就是说加上引用的是一个类型了.
至于能不能构成数组就在于这个类型的非凡性.

在 concepts of programming language中如是说:

C 语言包括了一种非凡的指针类型,被称为引用类型...
C 的引用类型变量是一个总是被隐式间接引用的,具有固定值的指针...
引用类型变量不能再被设置来引用任何其他变量.隐式间接引用阻止了对引用变量的地址的赋值.

他这里的这个说法,综合了引用类型的表现,引用类型的实现,属于实践派的说法.

而单从引用这个概念抽象地来看(理论派),需要storage吗...有很多问题可以思考.


网友回复:连人家估计一下“可能”你都要问为什么,你的为什么太多了,假如真这么好奇,应该自己多花花脑子,而不是去chase别人

引用 25 楼 Paradin 的回复:
引用 22 楼 baihacker 的回复:
没有引用构成的数组的理由:
标准:
8.3.2.4 There shall be no references to references, no arrys of references, and no pointer to references.

no references to references
这条标准可能会被修改...(我看的是98版的,不知道03版里怎么说的)


为什么会被修改

网友回复:好吧,规则就是规则了,别又上升为哲学了。
网友回复:把问题抛给别人很轻易,但是要问问自己:我思考了多少?我真的到不得不问别人的地步了?别人回答我的我都想明白了么?

抛出太多为什么,只会让自己在为什么的循环中迷失自我。问为什么是为了提高自己,而不是为了为什么而问为什么。

网友回复:我问是因为我恰好也找到了一个原因,并且我也做了分析:http://blog.csdn.net/Paradin/archive/2008/04/06/2254830.aspx,我不是瞎问哦~
所以我想知道他所知道的是也否包含我所想的~
网友回复:做人要厚道。假如你想和别人讨论你的想法,应该把你的想法先贴出来。否则你这样问问题会让人有拷问别人的感觉。合理的问法是:我想的对么?还有啥可能性等等。

我想任何“合理性”分析都只能是假设,说到底这只是一个语法规定,不一定有为什么。

引用 32 楼 Paradin 的回复:
我问是因为我恰好也找到了一个原因,并且我也做了分析:http://blog.csdn.net/Paradin/archive/2008/04/06/2254830.aspx,我不是瞎问哦~
所以我想知道他所知道的是也否包含我所想的~

网友回复:I agree.

by the way, so many "貌似..." :)
引用 28 楼 baihacker 的回复:
the storage of the array of refs leads to this problem
貌似要恰当些.

网友回复:你不觉得你25楼的问题问的轻易答得困难么?这么纠缠有意思么?假如baihacker 只是个猜测,一定会有为什么么?你是考察别人得“老师”么?

至于30楼,不要以为上升为哲学就是坏事情,哲学本身就是对一些常见规律性得一种归纳,只要有道理,就没有什么不好得。
网友回复:恩好的,我会学会厚道以及更加尊重的。
文法不也是人定的,设计新标准还不是从新文法甚至更低开始呀~
网友回复:[7] This problem appears with the standard binders, too. Bjarne Stroustrup has submitted a defect report to the Standards Committee. His proposal for a fix is to allow references to references and simply to treat them as references. At the time of this writing, the report was available at
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#106.

呵,我是有根据的...
网友回复:Good. Think before ask.
引用 31 楼 arong1234 的回复:
把问题抛给别人很轻易,但是要问问自己:我思考了多少?我真的到不得不问别人的地步了?别人回答我的我都想明白了么?

抛出太多为什么,只会让自己在为什么的循环中迷失自我。问为什么是为了提高自己,而不是为了为什么而问为什么。


网友回复:That's why I said all the rationality analysis is based on assumptions and guesses.
引用 34 楼 chao_83 的回复:
I agree.

by the way, so many "貌似..." :)
引用 28 楼 baihacker 的回复:
the storage of the array of refs leads to this problem
貌似要恰当些.

网友回复:
引用 37 楼 baihacker 的回复:
[7] This problem appears with the standard binders, too. Bjarne Stroustrup has submitted a defect report to the Standards Committee. His proposal for a fix is to allow references to references and simply to treat them as references. At the time of this writing, the report was available at
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#106.

呵,我是有根据的...


standard bind, 对,我当时发现的就是这个。想不到在这里确认了呵呵
网友回复:baihacker的那段话在哪找到的?那个[7]是?在你给的那个链接里没找到。(不是我又乱问,我找了下没找到。。)
网友回复:我也没有找到的说...
MCD里面5.12(呀,512)里的...
至于为什么有这个提议,理由应该可以想到的..
但是提议结果,我没有去查.(我还看的是98的标准呢)
网友回复:好的谢谢。
网友回复:
引用 4 楼 xiaocai0001 的回复:
1. 各个编译器都没有实现这样的语法

2. 编译器实现的难度较大, 实现数组的引用, 有可能出现栈空间的数组引用堆空间的元素, 或堆空间的数组引用栈空间的元素, 各变量元素的生存期处理将会很混乱

3. C/C 中数组的优势在于一片连续的内存空间. 亦即具有O(1)的随机存取特性, 支持数组元素引用后, 内存空间将不具有连续性. C/C 中数组与指针紧密联系, 由于内存空间的连续性, 则可以对a[2], 采用 int *p = &(a[0]), *(p 2)的…


学习了
网友回复:这个。。。看到大家讨论都很激烈啊,不知道是不是我给楼主的意思理解错了

经过测试,数组的引用应该是可以的,只是楼主的用法写的不对,现在还不清楚是不是编译器的扩展,得查书了
这种用法在参数传递的时候很有用
以下测试代码,VS2005编译通过,注重数组引用的声明语法
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/







#include "stdafx.h"

#include <iostream>

using namespace std;



void test(int(&array)[4])

{

    cout << sizeof(array) << endl;

    for(int i = 0; i < 4; i  )

        array[i] = 10 - i;

}



int main()

{

    int i[4] = {0};

    int(&j)[4] = i;

    cout << sizeof(i) << endl;

    cout << sizeof(j) << endl;

    for(int k = 0; k < 4; k  )

        i[k] = k;

    cout << "Initialize..." << endl;

    for(int k = 0; k < 4; k  )

        cout << i[k] << " ";

    cout << endl;

    for(int k = 0; k < 4; k  )

        cout << j[k] << " ";

    cout << endl;

    for(int k = 0; k < 4; k  )

        j[k] = 4-k;

    cout << "Modify..." << endl;

    for(int k = 0; k < 4; k  )

        cout << i[k] << " ";

    cout << endl;

    for(int k = 0; k < 4; k  )

        cout << j[k] << " ";

    cout << endl;

    test(i);

    cout << "Test..." << endl;

    for(int k = 0; k < 4; k  )

        cout << i[k] << " ";

    cout << endl;

    return 0;

}




由于连续内存的问题,数组的引用不能直接初始化数组元素,而应该是声明同样类型的数组标识符,并一要引用的数组表标识符进行初始化。其余所有操作与数组完全一样,包括sizeof()!
而假如要已数组的形式完成对多个同类型数据的引用,则7楼的方法可行。
欢迎大家拍砖。
网友回复:贴上测试运行结果看看:
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





16

16

Initialize...

0 1 2 3

0 1 2 3

Modify...

4 3 2 1

4 3 2 1

16

Test...

10 9 8 7

请按任意键继续. . .




网友回复:晕!似乎是理解错了楼主的意思了!
网友回复:lz问了半天为什么"no arrys of references",然后居然standard里的一句“ no arrys of references”就把lz打发了
网友回复:It is illegal to have an array of references, because pointers to references are not allowed and array names are coerced into pointers.

bc
网友回复:
引用 48 楼 CrySleeper 的回复:
lz问了半天为什么"no arrys of references",然后居然standard里的一句“ no arrys of references”就把lz打发了

没办法……问得都有人怒了……我太唠叨
网友回复:up
网友回复:数组的引用很麻烦!
网友回复:引用就是引用,引用不是造!
网友回复:这么个问题也这么多人顶...
引用的目的是什么?不就是用相同的地址进行内存操作,函数调用或者其他地方使用的时候可以直接修改它里面的内容而不需要进行内存复制吗?
懂了这个,然后知道数组名表示的就是地址,用数组名来操作和传递参数也是不需要复制内存的,只传递参数地址
那么要使用数组的引用还有必要吗?(且编译技术上也比较复杂)
网友回复:有时间了去干点儿正事儿!!!
整天扯这些没用的东西!
网友回复:又一个近乎讨论为什么1 1=2的话题。
C 是实用型语言,细节上很不完整和互融。当年就规定成这样了,这就够了。

网友回复:
引用 56 楼 taodm 的回复:
又一个近乎讨论为什么1 1=2的话题。
C 是实用型语言,细节上很不完整和互融。当年就规定成这样了,这就够了。

支持这种说话,有些东西还是需要去理解的。
网友回复:57楼少打了个不字吧。

引用 55 楼 sudamj 的回复:
有时间了去干点儿正事儿!!!
整天扯这些没用的东西!


对你们做应用的当然没有了,给你们规定什么就是什么了~
反馈还真不好找
网友回复:既然楼主这么想讨论1 1=2问题,那么我先反问一个
为什么有void *类型的变量(比如void * p;)却没有void型的变量(比如 void x;),当然就更加没有数组元素是void的。
又为什么不可以sizeof(void)? 又为什么不可以void * p = xxxx; p;?
网友回复:up
网友回复:这就是为什么现在很多语言不把void作为data type ,避免不必要得麻烦
网友回复:
引用 2 楼 gofqjyie 的回复:
晕,你的类型好歹也要匹配啊!
这种用法绝对错误.

网友回复:你那个引用
要引用多少个元素
编译器自己之前能确定下来吗
建议多研究一下引用的实质

网友回复:MARK~~
网友回复:
引用 18 楼 arong1234 的回复:
简而言之,12楼说的最貌似一个合理的原因。但是要说这一定能说服所有人,则不一定。

原因很简单,不是所有东西都有可信服的原因的。这只是C++语言的一个规定而已,可能是当时的写标准的人基于已经实现的东西达成的一个妥协,也许当时没有几个人认为“引用的数组”很有必要(我现在都认为无必要)。为什么需要把一个没什么大用处的东西加入标准了来增加编译器的复杂度呢?

所以,世界是不完美的,不是所有的东西都有“合…


顶,这才是最大的理由
网友回复:learning...
网友回复:我觉得:
引用是别名,
编译器看到的是一个引用声明(注重,严格意义上讲不存在引用的定义),你不能获取一个引用到底被安排在那里,是个什么东西,当然大部分可能会实现为指针
至于数祖,是一个定义,一段空间,用来存储东西的,存放引用干什么,存放编译器才知道的引用有什么意义?
网友回复:还没有想这么深奥的问题。
网友回复:实用吗?? 用法 用例 能简化程序, 能使运行速度加快 有什么值得研究的地方??
网友回复:
引用 65 楼 fuqd273 的回复:
引用 18 楼 arong1234 的回复:
简而言之,12楼说的最貌似一个合理的原因。但是要说这一定能说服所有人,则不一定。

原因很简单,不是所有东西都有可信服的原因的。这只是C++语言的一个规定而已,可能是当时的写标准的人基于已经实现的东西达成的一个妥协,也许当时没有几个人认为“引用的数组”很有必要(我现在都认为无必要)。为什么需要把一个没什么大用处的东西加入标准了来增加编译器的复杂度呢?

所以,世界是不完…

网友回复:C 规定,数组不能被引用,况且,数组有多个元素,即使引用也是第一个元素被引用,
网友回复:"你这个ref[]是从ref1和ref2拷贝了两个整数到数组,ref[0] = 1仍然不能改变i的值"

引用只是别名, 引用和被引用变量是同一个实体, 它们具有相同的地址, 它不可能变成另一个数组的成员,
因为,另一个数组的成员具有不同的地址, 你期望操作一个数组成员从而改变i, 只能使用指针

网友回复:让我来反证你的命题,

命题:C 数组元素可以是引用

前提:引用只是别名, 引用和被引用变量是同一个实体, 它们具有相同的地址(所有C 的同志都认同的, 呵呵)

设定:
int i;
....
int j;
...
int l;
...
int m;
...
int k;
...

int & arr[] = {i, j, k, l, m};

论证:
根据前提以及命题描述的, arr[0],arr[1],arr[2],arr[3],arr[4]实际上就是i、j、k、l、m五个变量本身,
然, 根据数组的定义, 数组成员的地址应该是连续的, 而实际上i、j、k、l、m的地址会是连续的吗? 不可能,
尤其是new出来的int, 这说明编译器根本无法实现这个命题

结论:
伪命题


网友回复:没啥说服力不说服力的。
对于一种语言来说,语法的制定,特性的取舍都是多种因素综合考虑的结果,某些时候甚至还会掺杂进政治因素。
因此,个人认为没有必要非要去寻求一个理论上的、让所有人都完全信服的原因。
至于各种非本质的原因(注重有时非本质的原因也能成为重要原因),楼上的朋友们已经给出好多了,偶就不再补充了。
网友回复::) 谢谢各位
网友回复:很清楚的。数组的元素一定需要确定的长度,比如T[10],它的长度一定是sizeof(T)*10.
但是引用是否需要内存、需要多少内存都是不确定的,并且你永远不能通过合法手段得到它的长度,当然不能作为数组的元素。

我们知道sizeof(T*)是一个指针的长度,但是sizeof(T&)却不是一个引用的长度,它等于sizeof(T)。从这点上也可以看出它们的区别。
从C开始,指针指向的类型就和数组的元素一样,都需要确定的长度,所以引用的数组、引用的指针都不会存在的。
但是引用的引用却没有这样的先天要求,将来有可能加入标准。

网友回复:
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/



     1: 

     2: #include   "stdafx.h"

     3: #include <iostream>

     4: #include <string>

     5: using namespace std;

     6: 

     7: int main()

     8: {

0041A690  push        ebp  

0041A691  mov         ebp,esp 

0041A693  sub         esp,144h 

0041A699  push        ebx  

0041A69A  push        esi  

0041A69B  push        edi  

0041A69C  lea         edi,[ebp-144h] 

0041A6A2  mov         ecx,51h 

0041A6A7  mov         eax,0CCCCCCCCh 

0041A6AC  rep stos    dword ptr es:[edi] 

     9: 

    10:     int i = 10, j = 20; 

0041A6AE  mov         dword ptr [i],0Ah  ; 变量名是内存地址,该内存所存储的为变量的值

0041A6B5  mov         dword ptr [j],14h  ; 变量名是内存地址,该内存所存储的为变量的值

    11:     int& ri = i, &rj = j;

0041A6BC  lea         eax,[i]            ; 变量地址

0041A6BF  mov         dword ptr [ri],eax ; 保存 变量地址 到 引用变量 的地址的内存中

0041A6C2  lea         eax,[j] 

0041A6C5  mov         dword ptr [rj],eax 

    12:     int k = 30, h = 40;

0041A6C8  mov         dword ptr [k],1Eh 

0041A6CF  mov         dword ptr [h],28h 

    13:     int* pk = &k;

0041A6D6  lea         eax,[k]            ; 变量地址

0041A6D9  mov         dword ptr [pk],eax ; 保存 变量地址 到 指针变量 的地址的内存中

    14:     //int& arr0[] = {i, j}; // C2234 因为不答应有指向引用的指针,所以不可能有引用数组。

    15:     int* arr1[] = {(int*)i, (int*)j}; // 强制转换为指针

0041A6DC  mov         eax,dword ptr [i] 

0041A6DF  mov         dword ptr [arr1],eax 

0041A6E2  mov         eax,dword ptr [j] 

0041A6E5  mov         dword ptr [ebp-5Ch],eax 

    16:     int* arr2[] = {&i, &j}; // 取变量的地址

0041A6E8  lea         eax,[i] 

0041A6EB  mov         dword ptr [arr2],eax 

0041A6EE  lea         eax,[j] 

0041A6F1  mov         dword ptr [ebp-6Ch],eax 

    17:     

    18:     int* arr3[] = {&ri, &rj}; // 取引用变量的地址(就是取引用变量所引用的那个变量的地址)

0041A6F4  mov         eax,dword ptr [ri] ; ex 就是 [i],见标记 11

0041A6F7  mov         dword ptr [arr3],eax 

0041A6FA  mov         eax,dword ptr [rj] 

0041A6FD  mov         dword ptr [ebp-7Ch],eax 

    19: 

    20:     if(arr2[0] == arr3[0])

0041A700  mov         eax,dword ptr [arr2] 

0041A703  cmp         eax,dword ptr [arr3] 

0041A706  jne         main 81h (41A711h) 

    21:     {

    22:         *arr2[1] = 200;

0041A708  mov         eax,dword ptr [ebp-6Ch] 

0041A70B  mov         dword ptr [eax],0C8h 

    23:     }

    24: 

    25:     *pk = h;

0041A711  mov         eax,dword ptr [pk] ; ex 就是 [k],见标记 13

0041A714  mov         ecx,dword ptr [h] 

0041A717  mov         dword ptr [eax],ecx 

    26:     ri = k;

0041A719  mov         eax,dword ptr [ri] ; ex 就是 [i],见标记 11

0041A71C  mov         ecx,dword ptr [k] 

0041A71F  mov         dword ptr [eax],ecx 

    27:     k = *pk;

0041A721  mov         eax,dword ptr [pk] 

0041A724  mov         ecx,dword ptr [eax] 

0041A726  mov         dword ptr [k],ecx 

    28:     // j 为 200

    29:     k = rj;

0041A729  mov         eax,dword ptr [rj] 

0041A72C  mov         ecx,dword ptr [eax] 

0041A72E  mov         dword ptr [k],ecx 

    30: 

    31:     return 0;

0041A731  xor         eax,eax 

    32: }



变量名是内存地址,该内存地址的内存所存储的为变量的值,见标记 10,

引用变量 和 指针变量 所代表的 内存地址 的内存都是保存着 变量地址,见标记 11 和 13,

取引用变量的地址,就是取引用变量所引用的那个变量的地址,见标记 18 和 16,

给引用变量赋值 和 给指针变量所指向的变量赋值一样,即 r 和 *p,见标记 26 和 25,


明白了这些,那么假设可以声明引用数组:

char& arr[] = {a, b};

那么 arr 的每一个元素都应该是 char& 引用变量,即一个内存地址,
好了,现在要访问数组 arr 的第 2 元素,那么该怎么计算第 2 个元素的地址呢?

是首地址 加上 char 的大小 1,还是 加上 内存地址 的 大小 4 ?

所以,不答应有指向引用的指针。

你可能会说,就 首地址 加上 内存地址 的 大小 4,这样就可以确定第 2 个元素的地址了,而且数组保存的是一个地址。

呵呵,那这不就是和指针数组一样吗?

char *arr[] = {&a, &b};

那你又说,就 首地址 加上 char 的大小 1,
好,这样的话,那么数组保存的应该是 char,而不是 char& 了。

呵呵,这样不是和普通数组一样吗?

char arr[] = {a, b};

所以,干嘛要引用数组呢?
网友回复:我觉得问题在于引用构成的数组不论怎么定义都让人很难理解,假如答应这样的语法存在,程序员使用过程中会非常轻易出错。
通常,引用我们可以理解成另外一个变量的别名
所以假如答应语法
int & arr[]={i, j};
那么也就是说arr[0]就是变量i,arr[1]就是变量j
而我们看到arr[0]和arr[1]时(数组形式),又会认为这两个变量在内存中是连续的。可是这一点编译器无法保证(比如i可以是局部变量,j可以是全局变量)。
而任何其他不同时满足上面要求的定义,只能引起使用者的头脑混乱
网友回复:[color=#FF0000]73楼的证实非常不错,很好地说明了引用数组不能存在地原因[/color]

网友回复:学习鸟,这种问题其实也有好处,可以让我们想到平时没有想过的地方,对于这种问题的反思,也有助于我们更加深刻的理解语言规范!

谢谢lz
网友回复:mark下,明天来了学习
网友回复:看了很多的帖子头晕了,要害是看到了73楼仁兄的帖子好象明白了...
我是这样理解的:
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/



int i = 100;


按理说,int在C 中占用4Byte空间,而实际占的空间要更多,因为程序中存在变量列表,用来保存各变量的名字,生命周期和作用域等信息
指针数组也好,普通变量数组也好,后是要把内存复制一份的。
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/



int i=100,j=101,k=102;

int array[] = {i,j,k};


我们需要的3个int数据一共用了12Byte,再加上array各元素,又复制了一份内存,程序这时候用了24Byte.
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/



int i=100,j=101,k=102;

int* pi,pj,pk;

pi = &i;

pj = &j;

pk = &k;

int* parray[] = {pi,pj,pk};


int*类型的数据部分也是4字节,这样i,j,k,pi,pj,pk和parray各元素一共用了36字节。
假如使用引用数组:
C/C code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/



int i=100,j=101,k=102;

int& refarray[] = {i,j,k};


这样,refarrar要指想一块连续内存的首地址,里面的数据,应当存的是变量名字的ACSII字符,但是变量名字可长可短,无法根据类型通过索引找到相应的数据.也就很难不能实现功能了,要想实现这样的功能,可能需要更复杂的在汇编基础上的超复杂算法。

事实上,我一直认为引用类型变量里面存的是非引用变量名字的ASCII码或者与之类似的相应的标识,有了这样的标识,才能通过引用变量找到实际变量,最终找到要用的数据。

菜的很,个人看法而已。
网友回复:补充:《深度探索C 对象模型》高深的很,这本书可能具体讲解了引用的知识
暂时还没看呢。
网友回复:指针数组的元素可以为null

可是C 的引用规定了一旦确定,不可更改。

如此这般,两个规定有冲突。所以……按照标准是不可以的

但,假如C 可以重新改变引用……

貌似C#就给实现了~呵呵。没必要。

另外,个人觉得,C 的引用是编译时确定,是别名,有点类似define,但有类型检查。
(此“另外”可以随意无视~)
网友回复:再次另外:
无论是那个高级语言的引用的汇编级实现还是相当于c/c 语言中的指针。变成机器代码过程中的过程不一样而已。
如此这样,还要硬去实现,有什么意义吗?
网友回复:学习~
网友回复:
char& arr[5];

sizeof(arr[0]) = ?
sizeof(arr) = ?
siseof(arr) / sizeof(arr[0]) = ?
网友回复:
引用 87 楼 cunsh 的回复:

char& arr[5];

sizeof(arr[0]) = ?
sizeof(arr) = ?
siseof(arr) / sizeof(arr[0]) = ?


sizeof(void)?????
sizeof(arr)亦可如此。
达成自相容的路不只一条,C 只不过选择了现在这条。
关键字:数组,元素,引用,说出,说服力,
上一篇:数组显示问题

相关文章

文章评论

共有 0 位网友发表了评论 此处只显示部分留言 点击查看完整评论页面