为什么我要使用引用变量?

kwo*_*ber 20 c++ pointers reference

作为我的第一门编程语言,我学习了Java,但是由于我改为另一所大学,我现在正在学习C++.

来自Java并学习C++的基础知识,我阅读了有关引用和引用变量的内容.它们有多危险,如何小心它们等等.

因此,在我脑海中出现了一个简单的问题:为什么我要使用那种复杂的,因此可能引起问题的东西呢?

它是不是值得,或者只是RAM大约64MB的时候的遗物?

由于很多答案都提到了指针:这个概念显然来自石器时代,imho.除了高性能计算,我甚至不会触及那些东西.

Ros*_*ost 8

问题与引用本身无关.

问题是在C++中,对象生存期的管理方式与使用垃圾收集器的Java或其他运行时环境不同.C++没有标准的内置垃圾收集器.C++对象生存期可以是自动的(在本地或全局范围内)或手动(在堆中显式分配/解除分配).

C++引用只是对象的简单别名.它对对象的生命周期一无所知(为了提高效率).程序员必须关心它.例外情况是引用绑定到临时对象的特殊情况; 在这种情况下,临时的生命周期延长到绑定引用的生命周期.细节在这里.

引用是C++基本概念的重要组成部分,您无法避免在90%的任务中使用它们.否则你必须使用指针,这通常更糟:-)

例如,当您需要通过引用而不是按值传递对象作为函数参数时,您可以使用引用:

void f(A copyOfObj);       // Passed by value, f receives copy of passed A instance
void f(A& refToObj);       // Passed by ref, f receives passed A instance itself, modifiable
void f(const A& refToObj); // Passed by const ref, f receives passed A instance itself, non modifiable
Run Code Online (Sandbox Code Playgroud)


pen*_*ope 6

由于您刚刚来自 Java,我可以想象您在使用 C/C++ 允许您执行的许多危险操作时遇到问题。在我看来,区别就在这里:

  • C/C++ 可以让你做很多强大危险的事情。你可以做很多伟大的事情,但也可能会搬起石头砸自己的腿
  • Java以安全的名义限制你可以做的事情

你不喜欢的(“指针/引用是危险的”)正是我喜欢的(“它让我做很多事情,如果我搞砸了,那是我的错”)。在我看来,这是编程语言品味的问题。

引用是为了避免指针的一些危险,但另一方面,除了明显的快速访问之外,即使指针仍然有用途。例如,假设您有一个低级对象,它执行一些有用的工作,并且在多个高级对象之间共享。它可以出于各种原因被共享(例如,它每次执行有用的工作时都会更新内部状态,因此复制它不是一个选项)。

class HL{
    private:
    LL &object;

    public:
    HL(LL &obj){
        object = obj; // initialization of reference
    }
    // a no-argument constructor is not possible because you HAVE to
    // initialize the reference at object-creation (or you could initialize
    // it to a dummy static object of type LL, but that's a mess)
    void some_routine(){
        ....
        object.useful_work();
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下使用引用会强制执行内部的初始化object。另一方面,如果对象提供的功能对于高级对象来说只是可选的,那么指针是一种可行的方法:

class HL{
    private:
    LL *object;

    public:
    HL(LL &obj){
        object = &obj; // initialization of reference
    }
    HL(){} // no-argument constructor possible
    void some_routine(){
        ....
        if (object != NULL)
           object->useful_work();
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,至于使用引用调用,当您将大结构传递给函数时,这是最有用的,例如vector<int>

void function(vector <int> a); // call by value, vector copied every time
void function(vector <int> &a); // call by reference, you can modify
                                // the vector in the function
void function(const vector <int> &a); // if you don't want to be able to modify
                                      // it, you can add const for "protection"
Run Code Online (Sandbox Code Playgroud)


Sur*_*ine 5

如果按值将大对象作为函数参数传递,则可能会有一个非常真实的性能下降,通过将它们作为引用传递来解决.此外,如果通过引用而不是值传递函数,则可以修改函数内的对象.


小智 5

引用是具有限制的指针.引用是访问对象的一种方式,但不是对象本身.如果您的代码使用这些限制是有意义的,那么使用引用而不是指针可以让编译器警告您不小心违反它们.


Jam*_*nze 5

最频繁使用引用是为了避免昂贵的深度复制;默认情况下,C++ 具有值语义,如果您编写如下内容:

void f( std::vector<double> d );
Run Code Online (Sandbox Code Playgroud)

每次调用时都会复制整个向量f。所以你写一些类似的东西:

void f( std::vector<double> const& d );
Run Code Online (Sandbox Code Playgroud)

这一点特别重要的地方是定义复制构造函数时。如果你要写:

MyType( MyType other );
Run Code Online (Sandbox Code Playgroud)

,您最终会得到无限递归,因为编译器必须调用复制构造函数才能将参数复制到此构造函数。(事实上​​,编译器只会接受一个引用复制构造函数的构造函数,正是为了避免这个问题。)

在构造函数之外,这实际上是一种优化,可以被视为过早优化。然而,在实践中,几乎通用的约定是通过引用 const 而不是通过值来传递类类型。

引用也可以用作输出参数;与指针相比,它们的优点是不能为空。

引用还可用于提供进入类数据的“窗口”。operator[]经典的例子是in的重载std::vector;它返回一个引用,以便您可以修改数组中的实际元素、获取其地址等。

除了作为参数和返回值之外,在上述情况下,引用是很少见的。例如,如果您使用一个作为类成员,您必须意识到您无法为该类提供经典的赋值语义。(如果类不支持赋值,这不是问题。)作为全局变量,它们可能用于隐藏所引用内容的实现,但这种情况极其罕见。作为局部变量,我知道的唯一用途是缓存另一个返回引用的表达式的结果:例如,如果我someMap[aKey]在一小段代码中多次访问,那么编写:

ValueType& element = someMap[aKey];
Run Code Online (Sandbox Code Playgroud)

在开始时使用,element之后使用。someMap[aKey](请注意,这只有在返回引用时才有意义。)