代码之家  ›  专栏  ›  技术社区  ›  Flash

C++中的引用

c++
  •  11
  • Flash  · 技术社区  · 16 年前

    我刚开始C++,遇到过引用,还没有完全理解。

    我读到的引用是对象的另一个名称。为什么使用它而不是直接访问对象,因为对引用的任何操作都直接反映在对象上…?

    1. 为什么以及何时使用?
    2. 就像一个常量指针,每次使用它时都会引用它…?

    它说

     double& dr = 1;  ----  says it is an error (some lavalue needed) 
     const double& cdr = 1;  ---- says it is ok. 
    

    我不太明白,所以请解释一下为什么…

    谢谢……)

    10 回复  |  直到 16 年前
        1
  •  11
  •   Justin Ardini    16 年前

    为什么不直接用它? 作为任何操作访问对象 参考文献直接反映在 物体…?

    C++通过参数传递参数,意思是如果你有一个函数,比如:

    void foo(MyObject o) { ... }
    

    默认情况下,C++将复制一个 MyObject , 不 直接使用正在传入的对象。因此,引用的一个用途是确保您正在处理同一个对象:

    void foo(MyObject &o) { ...}
    

    或者,如果您不修改 o :

    void foo(const MyObject &o) { ... }
    
        2
  •  3
  •   t0mm13b    16 年前

    引用是C代码最初的另一种方式

    void fubarSquare(int *x){
      int y = *x;
      *x = y * y;
    }
    
    // typical invocation
    int z = 2;
    fubarSquare(&z);
    // now z is 4
    

    用C++中的引用将是这样的

    void fubarSquareCpp(int& x){
       x = x * x;
    }
    
    // typical invocation
    int z = 2;
    fubarSquareCpp(z);
    // now z is 4
    

    这是使用 参考呼叫 参数,而不是使用C的符号星号/星号指示指针 参考呼叫 参数… 修改 直接在函数外部的参数…

    看看比亚恩·斯托斯特拉普的网页 here 它涵盖了C++是什么,这里也包含了技术常见问题。 here

        3
  •  3
  •   bradgonesurfing    16 年前

    引用基本上是一个看起来像对象的指针。很难得到一个空的引用,尽管你可以通过圈并创建一个。

    对于您的示例,1是一个右值或结果。它只是一个临时变量,不能修改。因此,不能将非常量引用它。但是,您可以使用常量引用。这意味着您不能更改引用的值。

    下面是创建空引用的示例。不要这样做!

    int * x = (int *)NULL;
    int & y = *x;
    
        4
  •  1
  •   neuro    16 年前

    我同意你的看法。将引用用作别名并不是很有用。 如果将其视为不可变指针,则更有用。但事实上没那么有用。

    实际上,它用于定义干净的接口。例如,当您定义:

    int foo(const int& param);
    

    您说param是foo中的只读参数。

    不要忘记必须为引用赋值。

    见 C++ faqlite 更多参考资料

    MY2C

        5
  •  1
  •   Stefan    16 年前

    引用改进了语法,因此不需要指针取消引用。 假设基是一个类,它可以从以下对象派生:

    void someFunction(Base b)
    {
        b.function();
        // b is a copy of what was passed - probably performance issues
        // possible unintended object slicing - you only get the Base part of it
        // no virtual function call
        // no changes to b visible outside the function
    }
    
    void someFunction(Base* b)
    {
        b->function();
        // a shortcut for (*b).function();
        // b is the same object that was passed to the function
        // possible virtual call
        // changes visible outside the function
    }
    
    void someFunction(Base& b)
    {
        b.function();
        // b is the same object that was passed to the function
        // possible virtual call
        // changes visible outside the function
    }
    

    引用类似于常量指针(不是指向常量的指针——也就是说,可以更改对象,但不能更改为指向的对象)。const-reference是一个引用,通过它可以对const对象进行操作。

    引用也很好,因为不能有空引用

        6
  •  1
  •   Bob Fincheimer    16 年前

    给予 wikipedia 文章通读得很好。综上所述,引用是指针的更友好版本,通常用于将对象作为引用传递到函数中,而不必担心空指针。

    要解释示例:


    想想这个数字 1 表示为变量。编译时,这个数字被放入内存的全局部分,程序可以引用该部分,但是 不 被改进的。

    所以它的类型是: 常数int

    double &dr = 1 正在尝试分配 dr (A) 对double的引用 ) const int 1 . 自从 一 是常量,编译器将不允许您对其进行非常量引用。

    在第二行:

    const double &dr = 1 正在尝试分配 博士 (A) 对double的常量引用 ) 常数int 1 . 这是因为 引用也是常量 因此可以指向 const int .

    编辑 这个 常数int 转换为 const double 在分配之前。

        7
  •  1
  •   jpalecek    16 年前

    引用是表示它们所引用的另一个对象的语言实体。非字符串引用是lvalue,必须用lvalue初始化。它们可以像这样有用:

    int& x=condition ? array[1] : array[2];
    int& y=condition ? array[0] : array[3];
    x+=y;
    y=0;
    

    当用作函数参数时,它们告诉调用方他必须传递一个可能由函数写入的左值:

    void set1(int& x) { x=1; }
    
    int foo;
    set1(foo); // ok, foo is 1
    set1(foo+1); // not OK, not lvalue
    

    另一方面,const引用可以绑定到rvalues。在函数参数中,它们通常用于避免过度复制:

    void niceness(std::string s); // the string would be copied by its copy-ctor
    void niceness(const std::string& s); // the caller's string would be used
    

    注意,这可能会或可能不会产生更快的代码。

    当常量引用在普通代码中使用时,它们也可以绑定rvalue,并且 as a special rule, they extend the lifetime of the object they are bound to . 这就是您在代码中看到的:

    const double& d=1; // OK, bind a rvalue to a const-ref
    double& d=1; // Bad, need lvalue
    

    所有引用都是多态的,比如指针:

    class A { virtual void f(); }
    class B : public A { void f(); }
    
    B b;
    A& ar=b;
    ar.f(); // calls B::f()
    

    所有引用都是别名,如指针:

    int f(int& a, const int& b)
    {
      a=1;
      return b;
    }
    
    int x;
    f(x, 42); // ==42, foo=1
    x=42;
    f(x, x); // ==1 (not 42), foo=1
    
        8
  •  0
  •   Bill    16 年前
    double& dr = 1; // 1.0 would be more clear
    

    是无效的,因为 1 被视为 const double 所以如果你想要一个对那个变量的引用,你需要一个对 双精度常数 所以

    const double& dr = 1.0;
    

    是正确的。

        9
  •  0
  •   jszpilewski    16 年前

    在向函数传递参数的上下文中,引用的实用程序最为明显。

    即,

    国际会计准则;

    func定义:void foo(int&param)param=1;

    函数调用:foo(a);

    “param”别名“a”的方式是干净的,它的意图很容易被此代码的读者和编译器理解,这些编译器可以在嵌入引用所需的任何其他内存分配时进行优化。

        10
  •  0
  •   supercat    16 年前

    将一个引用传递给一个函数,然后让该函数使用该引用,就像将一个指针传递给该函数,然后让该函数取消对该指针的引用一样。在许多情况下,机器代码实现是相同的。但是有一些区别,特别是在内联扩展函数的情况下。如果变量是通过引用传递给内联函数的,则编译器在扩展函数时通常能够替换变量本身——即使存储在机器寄存器中也是如此。相反,如果一个人把变量的地址作为一个指针传递给一个函数,然后将其取消引用,那么编译器就不太可能发现这种优化,除非它不仅确定——至少对于函数的一个特定扩展而言——指针将始终指向该变量,而且指针将将不在其他任何地方使用(如果指针在其他地方使用,则变量不能保存在寄存器中)。