指针和参考

Pointers & Reference

本文关键字:参考 指针      更新时间:2023-10-16

所以,我了解指针是什么,引用某个东西意味着什么,并且对这个"堆"有一个模糊的理解。当我们使用这些概念引入函数和类时,我开始失去对事物的控制,例如发送指针、返回指针等。

如果通过引用和传递指针本质上执行相同的功能,那么使用其中一个指针的优势是什么?两者本质上都是通过引用传递和在被调用函数之外操作对象。

因此,通过参考:

#include <iostream>
class student{
public:
    int semesterHours;
    float gpa;
};
void defRefS( student &refS );
void defPointerS( student *Ps );
void defValueS( student cS );
int main()
{
    student s;
    defRefS(s); //Here,
    std::cout << "nBack in main we have " << s.semesterHours << " hours";
    std::cout << "nBack in main the GPA is: " << s.gpa;

    student *Ps = &s;
    defPointerS(&s); //And here is where I get confused
    std::cout << "nBack in main we have " << s.semesterHours << " hours";
    std::cout << "nBack in main the GPA is: " << s.gpa;
    defValueS(s);
    std::cout << "nBack in main object S has: " << s.semesterHours << " hours";
    std::cout << "nBack in main object S has: " << s.gpa << " GPAnn";
}
void defRefS( student &refS ) //Passing by reference to object
{
    refS.gpa = 4.0;
    refS.semesterHours = 12;
    std::cout << "n------------- Reference Function ------------";
    std::cout << "nnObject S has: " << refS.semesterHours << " hours";
    std::cout << "nObject S has: " << refS.gpa << " GPA";
}
void defPointerS( student *Ps ) //Passing a pointer to the object
{
    Ps->gpa = 5.0;
    Ps->semesterHours = 14;
    std::cout << "nn------------- Pointer Function ---------------";
    std::cout << "nnNow object S has: " << Ps->semesterHours << " hours";
    std::cout << "nNow object S has: " << Ps->gpa << " GPA";
}
void defValueS( student cS ) //Passing the object by value
{
    cS.gpa = 100;
    cS.semesterHours = 50;
    std::cout << "nn------------- Value Function ------------------";
    std::cout << "nnObject S has: " << cS.semesterHours << " hours";
    std::cout << "nObject S has: " << cS.gpa << " GPA";
}

通过引用传递本质上允许符号相似,因为我想,在所有方面,refS都是s对象。因此,这带来了一种使用函数操作对象的简单方法。

传递指针很容易理解。它只是指向对象的指针。尽管在上面的代码中如何:

void defRefS( student &refS );
void defPointerS( student *Ps );
void defValueS( student cS );

是否所有这些函数都只定义为与学生类一起使用?那么,这些函数只能将对象的引用、指针和值传递给这个特定的类?

defRefS(s); //Here,
defPointerS(&s); //And here is where I get confused
defValueS(s);

如果通过引用传递,难道不应该传递对象的地址吗?因此,对我来说,自从在引用函数中传递指针函数的参数以来,它做了更多的事情。

函数defPointerS被定义为接受指针;我在给它发地址?

我猜您刚刚开始使用C++。不要担心堆,这是一个较低级别的概念,稍后您将了解它。如果您真的感兴趣,new操作符和malloc会在堆上分配内存(new实际上也会调用对象的构造函数,为您提供一个动态对象)。你可以把它想象成一个大空间,在那里你可以放你以后想要的东西)。

关于指针和引用,它们在大多数情况下是可互换的(正如您所了解的)。它只是取决于您想要如何构建代码。

在C++中,指针无处不在,人们通常传递指针而不是通过引用传递。指针使用频率更高的原因之一是动态内存分配的工作方式(new运算符或malloc)——它返回一个指针——而且你做了很多。所以通常你会通过给定的指针对对象进行操作。

在复制构造函数或定义运算符时,极少数情况下绝对必须使用引用。

我可能遗漏了一些案例,但这就是要点。

你会混淆与号(&)的两种用法。在一种情况下,它是一个运算符,而在另一种情况中,它是声明类型的一部分。

int x = 5;
int* y = &x; // (1) Here it's an operator
int& z = x;  // (2) Here it's part of the type of y

在上面的第(1)行中,我们声明并定义了一个名为y的变量,该变量的类型为pointer to int。这意味着变量y应该包含类型为int的变量的地址。要获取变量的地址,可以使用&作为运算符。因此,&xx的地址,我们将其存储在指针中。CCD_ 15现在是指向CCD_ 16的指针。

在第(2)行中,我们定义了一个名为z的变量,该变量的类型为reference to int。由于我们将x绑定到这个引用,这意味着我们可以使用z作为x的另一个名称。修改z将修改x(以及y指向的值!)。

因此,当你有一个接受指针的函数,比如void func(int* p),你需要给它传递int的地址。要做到这一点,你要么直接传递指针,要么接受int:的地址

int x = 5;
func(&x);

如果您有一个接受引用的函数,比如void func(int& r),那么您只需要向它传递一个int。参考文献将参考相同的int

int x = 5;
func(x);

这些可以以类似的方式使用:将参数传递给函数,以便函数可以对其进行修改或避免复制。但是,指针参数也允许将空指针传递给函数。这对引用不起作用,因为引用必须始终绑定到某个对象。此外,引用一旦绑定,就不能反弹到其他对象。

引用通常更方便,并且不依赖于C风格的指针操作。在C++中,您通常希望尽可能使用引用,必要时使用指针。有关详细信息,请参阅C++常见问题解答。

当您在函数/类型定义中使用字符&时(如在void defRefS( student &refS );student &refS中),您正在定义引用。该值将是一个参考。

当您在对象(变量)上使用相同的运算符(即:相同的字符&)时,您将获得该特定对象的地址(如在student *Ps = &s;defPointerS(&s);中)。该值将是一个指针。

还困惑吗?然后不要读下一句。运算符&也是按位AND,当在语句中时,例如0x1 & 0xFF产生1。返回值将是一个与语句中最大整数大小相当的整数。

使用其中一个的优势是什么

使用引用来传递函数的输入参数是有充分理由的:引用永远不能为NULL,所以不需要检查指针是否指向任何位置。

使用指针来传递函数的输入参数是有充分理由的:您可以使用指针算术,这样您就可以传递数组(这在c++中是不推荐的)。因此,在大多数情况下,最好坚持参考。

如果通过引用传递,难道不应该传递对象的地址吗-不,你按原样传递一个对象。参数附近的"与"表示该参数引用对象而不复制。

函数defPointerS被定义为接受指针;我在给它发地址-运算符"&"在应用于r值时生成指向对象的指针。

当您有student s;变量,并且您想将其传递给函数f,该函数接受类型为student(通过值传递)或student&(通过引用传递)的参数时,您只需调用f(s)。如果按值传递s,则会创建s的副本,并在函数体中使用s的副本。如果通过引用传递,则直接使用对象s。引用不能为NULL,这在许多情况下都是非常有利的。

当这个参数的类型是student*(也通过引用传递)时,您调用f(&s),因为指针需要用它将指向的地址初始化。

您还应该检查:指针与引用

对于初学者,请参阅C++中指针变量和引用变量之间的区别是什么?。

当通过引用传递变量时,您可以将其视为隐式获取地址,因此不必编写&,但它仍然在为你做这件事(这就是为什么如果你为引用参数传递一个像"5"这样的常数,你会得到一个错误)。它还隐式地在函数内部取消引用它,所以您也不必写"*"。

"函数defPointerS被定义为接受指针;我要给它发送地址?"指针是一个地址(或者更准确地说,是一个存储内存地址值的变量)。

"那么,这些函数只能将对象的引用、指针和值传递给这个特定的类?"这些类型表明,如果你试图将另一个类的实例传递给这个函数,你会收到编译器错误。然而,C++并没有强制执行类型安全性,您可以绕过它,强制它使用"relpret_cast"将指针传递到其他类型的对象。在大多数情况下,这是行不通的。