Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我为什么要使用引用变量呢? 作为我的第一个编程语言,我学习了java,但是自从我换到一个不同的大学,我现在学习C++。p> 来自java和C++的基础知识,我阅读了有关引用和引用变量。他们有多危险,如何小心对待他们等等_C++_Pointers_Reference - Fatal编程技术网

我为什么要使用引用变量呢? 作为我的第一个编程语言,我学习了java,但是自从我换到一个不同的大学,我现在学习C++。p> 来自java和C++的基础知识,我阅读了有关引用和引用变量。他们有多危险,如何小心对待他们等等

我为什么要使用引用变量呢? 作为我的第一个编程语言,我学习了java,但是自从我换到一个不同的大学,我现在学习C++。p> 来自java和C++的基础知识,我阅读了有关引用和引用变量。他们有多危险,如何小心对待他们等等,c++,pointers,reference,C++,Pointers,Reference,所以在我的脑海里出现了一个简单的问题: 为什么我要费心使用这种复杂的,因此可能导致问题的东西呢 这是值得的,还是仅仅是从RAM大约64MB大的时代遗留下来的 因为很多答案都提到了指针:这个概念显然来自石器时代。除了高性能的计算,我甚至不会碰那些东西 如果按值将大型对象作为函数参数传递,可能会出现非常真实的性能下降,通过将它们作为引用传递来解决。此外,如果通过引用而不是通过值传递对象,则可以修改函数中的对象。引用是带有限制的指针。引用是访问对象的一种方式,但不是对象本身。如果您的代码使用这些限制是

所以在我的脑海里出现了一个简单的问题: 为什么我要费心使用这种复杂的,因此可能导致问题的东西呢

这是值得的,还是仅仅是从RAM大约64MB大的时代遗留下来的


因为很多答案都提到了指针:这个概念显然来自石器时代。除了高性能的计算,我甚至不会碰那些东西

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

引用是带有限制的指针。引用是访问对象的一种方式,但不是对象本身。如果您的代码使用这些限制是合理的,那么使用引用而不是指针可以让编译器警告您意外违反这些限制。

例如,因为它们迫使您进行初始化,这会降低它们的危险性。

实际的问题是“为什么使用引用而不是指针”

我还没完全弄明白。目前,我使用引用

  • 因为你不能分配给他们。最坏的情况是,这对编译器没有任何意义,但编译器有可能利用这些知识

  • 通常,当我想要返回一个始终存在的指针,或者指示一个参数是必需的并且可能不是null ptr(没有null引用)时。这不是一条硬性规定;有时实际的指针感觉更自然

  • 当事情只是要求引用时,比如操作符重载


一般来说,我最终使用了很多引用,因为除非我真的需要一个实际的副本,否则我通常不想复制对象,而引用通常是有效的。

引用使得逐引用调用更容易,因为调用方在传递对象时不必使用
&
操作符

像这样:

MyObject ob;

void foo_ref(MyObject& o){ ...}
void foo_ptr(Myobject* o){ ...}

//call

foo_ref(ob);
foo_ptr(&ob);
此外,它们允许初始化函数中的指针:

MyObject* ob = nullptr;
MySubject* sub = nullptr;

void foo_init(MyObject *& o, MySubject *& s) {

   o = new MyObject;
   s = new MySubject;
}

//call

foo_init(ob, sub);
如果没有对指针的引用,这个示例将只使用指向指针的指针,这会使代码看起来很糟糕,因为您必须首先取消对每个参数的引用

MyObject* ob = nullptr;
MySubject* sub = nullptr;

void foo_init(MyObject ** o, MySubject ** s) {

   *o = new MyObject;
   *s = new MySubject;
}

//call

foo_init(&ob, &sub);

这个问题与引用本身无关

问题是,在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

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

void f( std::vector<double> d );
void f( std::vector<double> const& d );
定义副本构造函数时,这一点尤为重要。如果你要写:

MyType( MyType other );
ValueType& element = someMap[aKey];
,您将以无限递归结束,因为编译器 必须调用复制构造函数才能将参数复制到此构造函数。(事实上,编译器只接受构造函数 它引用了复制构造函数,正是为了避免这种情况 问题。)

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

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

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

除了作为参数和返回值之外,在上述情况下, 参考文献有点少。如果您使用一个作为类成员 例如,您必须意识到,您不能为类指定经典 赋值语义。(如果该类没有,则这不是问题 作为一个全局变量,它们可能用于隐藏 执行所提到的内容,但这是非常重要的 稀有的作为一个局部变量,我所知道的唯一用途是缓存 返回引用的另一个表达式的结果:例如,如果 我在一个短块中访问了大量的
someMap[aKey]
对于代码,编写以下代码是有意义的:

MyType( MyType other );
ValueType& element = someMap[aKey];
开始时,然后使用
元素
。(请注意,这只会使
因为
someMap[aKey]
返回了一个引用。)

因为你刚从Java来,我可以想象你在C/C++允许你做的很多危险的事情上遇到了问题。在我看来,区别在于:

  • C/C++可以让你做很多强大而危险的事情。你可以做一个l
    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"