C ++中的参考文献

时间:2010-08-17 13:08:06

标签: c++

我刚刚开始使用C ++并且遇到过引用并且没有完全理解。

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

  1. 为什么以及何时使用它们?
  2. 就像每次使用时引用的常量指针一样......?
  3. 而且,它说

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

    我不理解它。所以请解释为什么会这样......

    谢谢...... :)

10 个答案:

答案 0 :(得分:11)

  

为什么要使用它而不是直接使用它   以任何操作方式访问对象   关于引用的直接反映   对象......?

C ++按值传递参数,这意味着如果你有一个函数,如:

void foo(MyObject o) { ... }

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

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

或者,如果您不修改o

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

答案 1 :(得分:3)

引用基本上是一个看起来像对象的指针。获取NULL引用是非常困难的,尽管你可以通过箍并创建一个。

关于您的示例,1是右值或结果。它只是一个临时变量,无法修改。因此,您不能对它进行非const引用。但是你可以对它进行const引用。这意味着您无法更改参考值。

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

int * x = (int *)NULL;
int & y = *x;

答案 2 :(得分:3)

引用是最初在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的符号星号/星号来表示指针并作为按引用调用 这是一种更简洁的语法方法参数...和修改参数直接在函数外部...

查看Bjarne Stoustrap的页面here,其中介绍了C ++的内容以及技术常见问题here

答案 3 :(得分:1)

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

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

int foo(const int& param);

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

不要忘记你必须为参考分配一个值。

有关更多信息,请参阅C++ faqlite参考资料

MY2C

答案 4 :(得分:1)

仔细阅读wikipedia文章。总而言之,引用是更友好的指针版本,通常用于将对象作为引用传递给函数而不必担心空指针。

解释这个例子:


将数字1视为变量。编译时,此数字将放入内存的全局部分,该部分可由程序引用,但已修改。

所以类型为: const int

double &dr = 1正在尝试将dr对双的引用)分配给const int 1。由于1是一个常量,编译器不允许您对它进行非常量引用。

在第二行:

const double &dr = 1正在尝试为dr分配const int 1常量引用双)。这是有效的,因为引用也是const ,因此可以指向const int

修改 在分配之前,const int会转换为const double

答案 5 :(得分:1)

引用改进了语法,因此不需要指针解除引用。 假设Base是一个可以从以下派生的类:

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引用是一个引用,通过它可以执行可以在const对象上完成的事情。

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

答案 6 :(得分:1)

引用是代表他们引用的另一个对象的语言权限。 Nonconst引用是左值,必须用左值初始化。它们可以像这样有用:

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

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

当在普通代码中使用const-references时,它们也可以绑定rvalues和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

答案 7 :(得分:0)

double& dr = 1; // 1.0 would be more clear

无效,因为1被视为const double类型,因此如果您想要引用该变量,则需要引用const double所以

const double& dr = 1.0;

是对的。

答案 8 :(得分:0)

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

即,

int a;

func definition:void foo(int& param){param = 1;}

func call:foo(a);

作为'param'别名'a'的方式是干净的,并且这个代码的读者很容易理解它的意图,以及在内联引用所需的任何额外内存分配时可能优化的编译器。

答案 9 :(得分:0)

传递对函数的引用然后让函数使用引用几乎就像将指针传递给函数然后让函数取消引用指针。在许多情况下,机器代码实现将是相同的。但是,存在一些差异,尤其是在内联扩展的函数的情况下。如果通过引用内联函数传递变量,则编译器通常能够在扩展函数时替换变量本身 - 即使存储在机器寄存器中。相比之下,如果一个人获取变量的地址并将其作为指向函数的指针传递给函数然后取消引用它,则编译器不太可能找出该优化,除非它不仅仅确定 - 至少对于一个特定的扩展函数 - 指针将始终指向该变量,但指针也不会在其他地方使用(如果指针在别处使用,则变量无法保存在寄存器中)。