2012-02-12 178 views
1

所以,我明白指针是什么,引用什么意思,并且对这个“堆”有一个模糊的理解。当我们开始失去对事物的控制时,就是当我们使用这些概念引入函数和类时,例如发送指针,返回指针等。指针与参考

如果通过引用和传递指针本质上执行相同的功能,那么使用它们的优点是什么?基本上都是通过引用传递并在被调用的函数之外操作对象。

因此,通过参考:

#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 << " GPA\n\n"; 

} 

void defRefS(student &refS) //Passing by reference to object 
{ 
    refS.gpa = 4.0; 
    refS.semesterHours = 12; 
    std::cout << "\n------------- Reference Function ------------"; 
    std::cout << "\n\nObject 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 << "\n\n------------- Pointer Function ---------------"; 
    std::cout << "\n\nNow 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 << "\n\n------------- Value Function ------------------"; 
    std::cout << "\n\nObject S has: " << cS.semesterHours << " hours"; 
    std::cout << "\nObject S has: " << cS.gpa << " GPA"; 
} 

按引用传递本质上允许的符号是类似的,因为,我想,在各方面refSs对象。所以,这导致使用函数来操纵对象的简单方法。

传递指针很容易理解。它只是一个指向对象的指针。虽然在以上代码中如何处理:

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被定义为接受指针;我正在发送地址?

+1

谁告诉你这个所谓的“堆”不应该支付的“教你的C++”。取而代之的是一本好书。 – 2012-02-12 20:18:10

+0

@KerrekSB我没有看到教授动态管理变量的常见实现的问题 – 2012-02-12 20:41:23

+0

@SethCarnegie:一百个困惑的SO问题,应该从来都不足以成为我的理由...... – 2012-02-12 20:43:13

回答

1

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

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

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

0

当你有student s;变量,你想通过它来运作f这需要student类型(按值传递),或student&(通过引用传递)的说法,你只需要调用f(s)。如果按值通过s,则会创建s的副本,并在函数体中使用s的副本。如果通过引用传递它,则直接使用对象s。引用不能为NULL,这在很多情况下都是很有利的。

当这个参数的类型是student*(也通过引用传递)时,由于指针需要用指向它的地址进行初始化,因此可以调用f(&s)

您也应该检查:Pointer vs. Reference

2

我猜你是刚开始在C++中。不要担心堆,这是一个较低层次的概念,您将在稍后了解这些概念。如果你真的感兴趣,new运算符和malloc在堆上分配内存(new实际上也调用对象的构造函数,给你一个动态对象)。你可以把它看作只是一个空间,你可以放入你想要的东西)。

关于指针和引用,它们在大多数情况下都是可以互换的(正如你想象的那样)。这取决于你想如何构建你的代码。

在C++中,指针无处不在,人们通常会传递指针而不是通过引用传递。指针被更频繁地使用的原因之一是因为动态内存分配的工作原理(new运算符或malloc) - 它返回一个指针 - 并且你做了很多工作。所以一般来说,你会通过指针指向一个对象。

绝对必须使用引用的罕见场合是在复制构造函数或定义运算符中。

我可能错过了一些情况,但这是它的要点。

+1

'new'不是(仅仅)关于分配;最重要的是它创建一个动态*对象*(即它调用构造函数)。不要混淆记忆和物体;它们在C++中是不同的概念。 – 2012-02-12 20:39:46

+0

这是真的,我会解决这个问题。 – Pochi 2012-02-12 20:55:19

+1

新的不会像malloc一样在堆上分配内存;它分配它在免费商店 – 2012-02-12 21:34:57

0

初学者请参阅What are the differences between pointer variable and reference variable in C++?

当通过引用传递变量,你可以把它看作含蓄地地址,这样你就不必写&,但它仍然这样做是为了你(这就是为什么你会得到,如果一个错误你传递一个常量,如“5”作为参考参数)。它也隐含在函数内部解引用它,所以你不必写“*”。

“函数defPointerS被定义为接受指针;我正在发送它的地址?”指针是一个地址(或者更恰当的说,是一个存储内存地址值的变量)。

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

1

使用一个优于另一个的优点是什么?

很好的理由使用供输入参数函数的引用:参考永远不能为空,这样你就不会需要检查是任何地方的指针指向。

使用指针传递函数的输入参数的好理由:您可以使用指针算术,因此您可以传递数组(这在C++中不推荐)。所以最好在大多数情况下坚持引用。

如果按照引用传递,你不应该传递一个对象的地址吗? - 不,你传递一个对象。和号附近的参数意味着参数在不复制的情况下引用对象。

函数defPointerS被定义为接受指针;我正在发送地址? - 应用于r值时的运算符“&”产生指向对象的指针。

2

你得到的符号(&)的两种用法之间的混淆。在一种情况下,它是一个操作员,在另一种情况下,它是声明类型的一部分。

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的地址,我们将它存储在指针中。 y现在是指向x的指针。在第(2)行中,我们定义了一个变量z,其类型为reference to int。由于我们绑定X本refernece,这意味着我们可以使用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++中,您通常只需要使用引用,如果必须使用指针。详情请参阅the C++ FAQ