Ссылки в С++

Я только что начал С++ и столкнулся с ссылками и не понял полностью.

Ссылки, поскольку я читаю это альтернативное имя для объекта. Почему это используется вместо прямого доступа к объекту, поскольку любая операция над ссылками непосредственно отражается на объекте...?

  • Почему и когда они используются?
  • Is ist как постоянный указатель, который ссылается каждый раз, когда он используется...?

И он говорит

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

Я не понимаю его правильно. Пожалуйста, объясните, почему это так...

Спасибо...:)

Ответ 1

Зачем использовать это вместо прямого доступ к объекту как к любой операции по ссылкам непосредственно отражается на объект...?

С++ передает параметры по значению, что означает, если у вас есть такая функция, как:

void foo(MyObject o) { ... }

По умолчанию С++ сделает копию MyObject, а не напрямую использует передаваемый объект. Таким образом, одно использование ссылок заключается в том, чтобы вы работали над одним и тем же объектом:

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

Или, если вы не изменяете o:

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

Ответ 2

Ссылка - это в основном указатель, который выглядит как объект. Очень сложно получить ссылку NULL, хотя вы можете пройти через обручи и создать ее.

Что касается вашего примера, 1 - это rvalue или результат. Это просто временная переменная и не может быть изменена. Таким образом, вы не можете ссылаться на него. Однако вы можете использовать константную ссылку на него. Это означает, что вы не можете изменить значение ссылки.

Вот пример создания ссылки NULL. Не делай этого!

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

Ответ 3

Ссылки - это еще один способ того, что изначально было в C-коде, как этот

void fubarSquare(int *x){
  int y = *x;
  *x = y * y;
}

// typical invocation
int z = 2;
fubarSquare(&z);
// now z is 4

со ссылками в С++ это будет как

void fubarSquareCpp(int& x){
   x = x * x;
}

// typical invocation
int z = 2;
fubarSquareCpp(z);
// now z is 4

Это более аккуратный синтаксический способ использования параметра для вызова по ссылке вместо того, чтобы использовать звездочку или звезду обозначений C, чтобы указать указатель и как параметр для вызова по ссылке... и изменить параметр непосредственно вне функции...

Взгляните на страницу Bjarne Stoustrap здесь, которая описывает, как С++ есть, а также здесь, на техническом faq здесь

Ответ 4

Я согласен с тобой. использование ссылок в качестве имени псевдонима не очень полезно. Это более полезно, если вы считаете его неизменным указателем. Но это не так полезно.

Практически он используется для определения чистых интерфейсов. Например, когда вы определяете:

int foo(const int& param);

Вы говорите, что param является параметром только для чтения в foo.

Не забывайте, что вы ДОЛЖНЫ назначить значение ссылке.

Смотрите С++ faqlite в ссылках для более

my2c

Ответ 5

Дайте wikipedia статью хорошо прочитать. Подводя итог, ссылки являются более дружественной версией указателей, которые обычно используются для передачи объектов в качестве ссылок в функции, не беспокоясь о нулевом указателе.

Чтобы объяснить пример:


Подумайте о количестве 1, представленном как переменная. При компиляции это число помещается в глобальный раздел памяти, на который может ссылаться программа, но не.

Итак, это тип: const int

double &dr = 1 пытается назначить dr (a ссылку на двойную) на const int 1. Поскольку 1 является константой, компилятор не позволит вам ссылаться на него.

Во второй строке:

const double &dr = 1 пытается назначить dr (a постоянную ссылку на double) const int 1. Это работает, потому что ссылка также const и поэтому может указывать на const int.

ИЗМЕНИТЬ const int преобразуется в const double перед назначением.

Ответ 6

Ссылки улучшают синтаксис, поэтому не требуется разыменование указателя. Предполагаемая база - это класс, который может быть получен из:

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.

Ссылки также хороши, потому что вы не можете иметь нулевую ссылку

Ответ 7

Ссылки - это языковые права, которые представляют собой другой объект, к которому они относятся. Ссылки nonconst являются значениями lvalues ​​и должны быть инициализированы lvalue. Они могут быть полезны следующим образом:

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

При использовании в качестве параметра функции они сообщают вызывающему, что он должен передать значение l, которое может быть записано функцией:

void set1(int& x) { x=1; }

int foo;
set1(foo); // ok, foo is 1
set1(foo+1); // not OK, not lvalue

С другой стороны, ссылки на константу могут быть связаны с rvalues. В функциональных параметрах они обычно используются, чтобы избежать чрезмерных копий:

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

Обратите внимание, что это может привести или не приведет к более быстрому коду.

Когда константные ссылки используются в нормальном коде, они также могут связывать значения rvalues ​​и в качестве специального правила, они продлевают время жизни объекта, который они связаны с. Это то, что вы видели в своем коде:

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

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

Недопустимо, потому что 1 считается типом const double, поэтому, если вам нужна ссылка на эту переменную, вам нужно иметь ссылку на const double, поэтому

const double& dr = 1.0;

Правильно.

Ответ 9

Утилита ссылок наиболее заметна в контексте передачи параметров функциям.

то есть,

int a;

определение func: void foo (int & param) {param = 1;}

func call: foo (a);

Путь как "param" aliases "a" чист, и его намерение легко понять читателю этого кода, а также компилятору, который может оптимизироваться при встраивании любого дополнительного выделения памяти, необходимого для ссылки.

Ответ 10

Передача ссылки на функцию, а затем использование этой функции используется почти так же, как передача указателя на функцию, а затем функция разыменовывает указатель. Во многих случаях реализация машинного кода будет идентичной. Однако есть некоторые различия, особенно в случае функций, которые расширяются внутри. Если переменная передается по ссылке на встроенную функцию, то при расширении функции компилятор часто сможет заменить сама переменную - даже если она хранится в машинном регистре. В отличие от этого, если вы берете адрес переменной и передаете это как указатель на функцию, которая затем разыгрывает ее, компилятор с меньшей вероятностью будет определять эту оптимизацию, если только она не определяет не только это - по крайней мере, для одного конкретного расширения функция - указатель всегда укажет на эту переменную, но также и то, что указатель не будет использоваться где-либо еще (если указатель использовался в другом месте, переменная не может храниться в регистре).