C++ 指向数组的引用和指针如何彼此不同?哪一个更可取?

C++ 指向数组的引用和指针如何彼此不同?哪一个更可取?,c++,arrays,pointers,reference,C++,Arrays,Pointers,Reference,我是一个cpp初学者,一直在尝试非常基本的方法。我研究了引用和指针在数组方面的区别,并编写了一个简单的代码片段 int main() { //char * c2 = "C"; //std::cout << &c2<<std::endl; //std::cout << *c2<<std::endl; int arr[]={21,2,3,4,5,6,7,8,9,10}; int (&a

我是一个cpp初学者,一直在尝试非常基本的方法。我研究了引用和指针在数组方面的区别,并编写了一个简单的代码片段


int main() {
    //char *  c2 = "C";
  //std::cout << &c2<<std::endl;
    //std::cout << *c2<<std::endl;
    int arr[]={21,2,3,4,5,6,7,8,9,10};
    int (&ar)[10]=arr;
    int *ar1=arr;
    std::cout<<"add of arr[0] :"<<&arr[0]<<std::endl;
    std::cout<<"value of ar: "<<ar<<std::endl;
    std::cout<<"value of ar1: "<<ar1<<std::endl;
    std::cout<<"value of *ar: "<<*ar<<std::endl;
    std::cout<<"value of *ar1: "<<*ar1<<std::endl;
    std::cout<<"value of *(ar+1): "<<*(ar+1)<<std::endl;
    std::cout<<"value of *(ar1+1): "<<*(ar1+1)<<std::endl;
    std::cout<<"value of ar[0]: "<<ar[0]<<std::endl;//some garbage value
    std::cout<<"value of ar1[0]: "<<ar1[0]<<std::endl;//some garbage value
    std::cout<<"value of sizeof(ar): "<<sizeof(ar)<<std::endl;
    std::cout<<"value of sizeof(int): "<<sizeof(int)<<std::endl;
    std::cout<<"value of sizeof(arr): "<<sizeof(arr)<<std::endl;
    std::cout<<"value of sizeof(ar1): "<<sizeof(ar1)<<std::endl;
}
正如您所看到的,我能发现的唯一区别是引用的大小不同于指针的大小。实际上,引用和指针的值都是数组的第一个元素。即使是指针算法,它们的工作方式也是一样的。引用的大小是int*10,指针的大小是8。这到底是怎么回事?这两种方法有什么不同?对于何时使用参考或指针,是否有标准的做法

引用的大小是int*10,指针的大小是8

引用是别名,因此引用的大小是
int*10
,这与
sizeof(arr)

这两种方法有何不同?是否有一种标准做法 何时使用引用或指针

当您不需要控制对象的生存期时,更喜欢使用引用。当您发现引用不能满足您的要求时,我们必须使用指针

参考与指针:

  • 必须初始化引用
  • 指针不必初始化
  • 引用可以挂起,指针也可以挂起
  • 控制资源所有权的指针需要删除以避免资源泄漏(我们可以使用智能指针来避免)
您还可以阅读以获取有关选择参考与指针的更多信息

引用的大小是int*10,指针的大小是8

引用是别名,因此引用的大小是
int*10
,这与
sizeof(arr)

这两种方法有何不同?是否有一种标准做法 何时使用引用或指针

当您不需要控制对象的生存期时,更喜欢使用引用。当您发现引用不能满足您的要求时,我们必须使用指针

参考与指针:

  • 必须初始化引用
  • 指针不必初始化
  • 引用可以挂起,指针也可以挂起
  • 控制资源所有权的指针需要删除以避免资源泄漏(我们可以使用智能指针来避免)

您还可以阅读以下内容,以获取有关选择参考与指针的更多信息:简化说明:

指针是一种需要足够大才能存储任何地址的类型。在您的系统上,所需的大小为8字节。您可以使用指针进行操作,而无需实际更改指针指向的变量
sizeof
不会给出数组的大小,而是指针的大小。请注意,
sizeof*ar1
也不应该给出大小,它只给出数组的第一个元素的大小,即
int

一个引用基本上是一个指针上的语法糖,这个指针对于真正的按引用传递有一些额外的能力。对于引用和指针,编译器可以使用引用和指针生成相同/非常相似的程序集/机器代码。例如,这两个功能:

int foo(int &bar)
{
    return ++bar;
}
int baz(int *bar)
{
    return ++(*bar);
}
生成与GCC 10.2和
-O1
相同的程序集(选中):

foo(int&):
mov eax,DWORD PTR[rdi]
添加eax,1
mov DWORD PTR[rdi],eax
ret
巴兹(国际*):
mov eax,DWORD PTR[rdi]
添加eax,1
mov DWORD PTR[rdi],eax
ret
(对于
-O0
-O2
-O3
处的两个功能,生成的程序集也是相同的)

正如你所看到的,完全一样


但是,是的,引用比指针更有力量。如您所见,
sizeof
给出了数组的实际大小,而对于指针,它只给出了指针的大小。此外,对于
常量T&
T&
的情况,引用也可以接受右值,而指针不能接受右值。

一个简化的解释:

指针是一种需要足够大才能存储任何地址的类型。在您的系统上,所需的大小为8字节。您可以使用指针进行操作,而无需实际更改指针指向的变量
sizeof
不会给出数组的大小,而是指针的大小。请注意,
sizeof*ar1
也不应该给出大小,它只给出数组的第一个元素的大小,即
int

一个引用基本上是一个指针上的语法糖,这个指针对于真正的按引用传递有一些额外的能力。对于引用和指针,编译器可以使用引用和指针生成相同/非常相似的程序集/机器代码。例如,这两个功能:

int foo(int &bar)
{
    return ++bar;
}
int baz(int *bar)
{
    return ++(*bar);
}
生成与GCC 10.2和
-O1
相同的程序集(选中):

foo(int&):
mov eax,DWORD PTR[rdi]
添加eax,1
mov DWORD PTR[rdi],eax
ret
巴兹(国际*):
mov eax,DWORD PTR[rdi]
添加eax,1
mov DWORD PTR[rdi],eax
ret
(对于
-O0
-O2
-O3
处的两个功能,生成的程序集也是相同的)

正如你所看到的,完全一样


但是,是的,引用比指针更有力量。如您所见,
sizeof
给出了数组的实际大小,而对于指针,它只给出了指针的大小。另外,对于
常量T&
T&
的情况,引用也可以接受右值,而指针不能接受右值。

下面的线程是否回答了您的问题?以下线程是否回答了您的问题?