Используйте establish_connection
для переключения в другую базу данных:
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "myuser",
:password => "mypass",
:database => "somedatabase"
)
Вы также можете передать предварительно сконфигурированную среду из database.yml следующим образом:
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['other_env'])
Вы также можете установить его для определенной модели:
MyClass.establish_connection(...)
int x = 5;
int y = 6;
int *p;
p = &x;
p = &y;
*p = 10;
assert(x == 5);
assert(y == 10);
Ссылка не может быть назначена и должна быть назначена при инициализации: int x = 5;
int y = 6;
int &r = x;
int x = 0;
int &r = x;
int *p = &x;
int *p2 = &r;
assert(p == p2);
int x = 0;
int y = 0;
int *p = &x;
int *q = &y;
int **pp = &p;
pp = &q;//*pp = q
**pp = 4;
assert(y == 4);
assert(x == 0);
nullptr
напрямую, тогда как ссылка не может. Если вы достаточно стараетесь, и знаете, как это сделать, вы можете сделать адрес ссылки nullptr
. Аналогично, если вы достаточно стараетесь, вы можете иметь ссылку на указатель, а затем эта ссылка может содержать nullptr
. int *p = nullptr;
int &r = nullptr; <--- compiling error
int &r = *p; <--- likely no compiling error, especially if the nullptr is hidden behind a function call, yet it refers to a non-existent int at address 0
++
, чтобы перейти к следующему элементу, на который указывает указатель, и + 4
, чтобы перейти к 5-му элементу. Это независимо от того, какой размер указывает объект, на который указывает указатель. *
, чтобы получить доступ к адресу памяти, на которое он указывает, тогда как ссылку можно использовать напрямую. Указатель на класс / структура использует ->
для доступа к своим членам, тогда как ссылка использует .
. const int &x = int(12); //legal C++
int *y = &int(12); //illegal to dereference a temporary.
Это делает const&
более безопасным для использования в списках аргументов и т. Д. Кроме того, ссылка, которая является параметром для функции, которая является встроенной, может обрабатываться иначе, чем указатель.
void increment(int *ptrint) { (*ptrint)++; }
void increment(int &refint) { refint++; }
void incptrtest()
{
int testptr=0;
increment(&testptr);
}
void increftest()
{
int testref=0;
increment(testref);
}
Многие компиляторы при встраивании указателя версии один на самом деле вынуждают запись в память (мы берем адрес явно). Тем не менее, они оставят ссылку в регистре, который является более оптимальным.
Конечно, для функций, которые не включены, указатель и ссылка генерируют один и тот же код, и всегда лучше передавать свойства по значению, а не по если они не изменены и не возвращаются функцией.
Существует одно фундаментальное различие между указателями и ссылками, которые я не видел никого, о которых упоминалось: ссылки позволяют использовать семантику pass-by-reference в аргументах функции. Указатели, хотя сначала это не видно, нет: они предоставляют только семантику pass-by-value. Это было очень хорошо описано в этой статье .
С уважением, & amp; rzej
Я чувствую, что есть еще один момент, который здесь не был рассмотрен.
В отличие от указателей ссылки синтаксически эквивалентны объекту, к которому они относятся, т. е. любая операция, которая может быть применена к объекту, работает для ссылки, и с тем же синтаксисом (исключение, конечно, инициализация).
Хотя это может показаться поверхностным, я считаю, что это свойство имеет решающее значение для ряда функций C ++, например:
T
, так и с T&
. (или std::reference_wrapper<T>
, который все еще полагается на неявный приведение к T&
). Шаблоны, которые охватывают как T&
, так и T&&
, еще более распространены. str[0] = 'X';
Без ссылок он будет работать только для c-строк (char* str
). Возврат символа по ссылке позволяет пользовательским классам иметь одну и ту же нотацию. operator+(const T& a, const T& b)
, сохраняя одну и ту же инфиксную нотацию. Это также работает для регулярных перегруженных функций. Эти точки дают значительную часть C ++ и стандартной библиотеки, поэтому это довольно важное свойство ссылок.
Помимо синтаксического сахара, ссылка является указателем const
( not указателем на const
). Вы должны установить, к чему это относится, когда вы объявляете ссылочную переменную, и вы не можете изменить ее позже.
Обновление: теперь, когда я думаю об этом еще, есть важное различие.
Целью указателя const можно заменить его адрес и использовать const cast.
Цель ссылки не может быть заменена каким-либо образом, чем UB.
Это должно разрешить компилятор, чтобы сделать большую оптимизацию по ссылке.
T* const
с различным синтаксическим сахаром (что случается, чтобы устранить много * и & amp; из вашего кода).
– Carlo Wood
10 January 2017 в 02:34
cout << 42 << "hello" << endl
без ссылок
– pm100
11 January 2018 в 20:55
int i; int const *pci = &i; /* implicit conv to const int* */ int *pi = const_cast<int*>(pci);
в порядке.
– curiousguy
29 June 2018 в 16:00
Эта программа может помочь в понимании ответа на вопрос. Это простая программа ссылки «j» и указатель «ptr», указывающий на переменную «x».
#include<iostream>
using namespace std;
int main()
{
int *ptr=0, x=9; // pointer and variable declaration
ptr=&x; // pointer to variable "x"
int & j=x; // reference declaration; reference to variable "x"
cout << "x=" << x << endl;
cout << "&x=" << &x << endl;
cout << "j=" << j << endl;
cout << "&j=" << &j << endl;
cout << "*ptr=" << *ptr << endl;
cout << "ptr=" << ptr << endl;
cout << "&ptr=" << &ptr << endl;
getch();
}
Запустите программу и посмотрите на результат, и вы поймете.
Кроме того, забудьте 10 минут и посмотрите это видео: https://www.youtube.com/watch?v=rlJrrGV0iOg
void Foo::bar() { virtual_baz(); }
, который segfaults. Если вы не знаете, что ссылки могут быть нулевыми, вы не можете отследить нуль до его начала.
– cmaster
29 December 2014 в 11:43
int &r=*p;
- неопределенное поведение. В этот момент у вас нет «ссылки, указывающей на NULL», у вас есть программа, о которой больше не может рассуждать о вообще . i>
– cdhowie
28 March 2017 в 18:46
Ссылка на указатель возможна в C ++, но обратное невозможно, поскольку указатель на ссылку невозможен. Ссылка на указатель обеспечивает более чистый синтаксис для изменения указателя. Посмотрите на этот пример:
#include<iostream>
using namespace std;
void swap(char * &str1, char * &str2)
{
char *temp = str1;
str1 = str2;
str2 = temp;
}
int main()
{
char *str1 = "Hi";
char *str2 = "Hello";
swap(str1, str2);
cout<<"str1 is "<<str1<<endl;
cout<<"str2 is "<<str2<<endl;
return 0;
}
И рассмотрите версию C вышеуказанной программы. В C вы должны использовать указатель на указатель (множественная косвенность), и это приводит к путанице, и программа может выглядеть сложной.
#include<stdio.h>
/* Swaps strings by swapping pointers */
void swap1(char **str1_ptr, char **str2_ptr)
{
char *temp = *str1_ptr;
*str1_ptr = *str2_ptr;
*str2_ptr = temp;
}
int main()
{
char *str1 = "Hi";
char *str2 = "Hello";
swap1(&str1, &str2);
printf("str1 is %s, str2 is %s", str1, str2);
return 0;
}
Для получения дополнительной информации о ссылке на указатель посетите следующую страницу:
Как я уже сказал, указатель на ссылку невозможен. Попробуйте следующую программу:
#include <iostream>
using namespace std;
int main()
{
int x = 10;
int *ptr = &x;
int &*ptr1 = ptr;
}
Еще одно интересное использование ссылок состоит в том, чтобы предоставить аргумент по умолчанию для пользовательского типа:
class UDT
{
public:
UDT() : val_d(33) {};
UDT(int val) : val_d(val) {};
virtual ~UDT() {};
private:
int val_d;
};
class UDT_Derived : public UDT
{
public:
UDT_Derived() : UDT() {};
virtual ~UDT_Derived() {};
};
class Behavior
{
public:
Behavior(
const UDT &udt = UDT()
) {};
};
int main()
{
Behavior b; // take default
UDT u(88);
Behavior c(u);
UDT_Derived ud;
Behavior d(ud);
return 1;
}
По умолчанию используется «привязка const const к временному» аспекту ссылок.
Существует очень важное нетехническое различие между указателями и ссылками: аргумент, передаваемый функции указателем, гораздо более заметен, чем аргумент, переданный функции с помощью неконстантной ссылки. Например:
void fn1(std::string s);
void fn2(const std::string& s);
void fn3(std::string& s);
void fn4(std::string* s);
void bar() {
std::string x;
fn1(x); // Cannot modify x
fn2(x); // Cannot modify x (without const_cast)
fn3(x); // CAN modify x!
fn4(&x); // Can modify x (but is obvious about it)
}
Назад на C, вызов, который выглядит как fn(x)
, может передаваться только по значению, поэтому он определенно не может изменить x
; для изменения аргумента вам нужно будет передать указатель fn(&x)
. Поэтому, если аргументу не предшествовал &
, вы знали, что он не будет изменен. (Обратное, &
означает изменение, было неверным, потому что иногда вам приходилось передавать большие структуры только для чтения указателем const
.)
Некоторые утверждают, что это такая полезная функция при чтении кода, то параметры указателя всегда должны использоваться для изменяемых параметров, а не для ссылок const
, даже если функция никогда не ожидает nullptr
. То есть, эти люди утверждают, что сигнатуры функций, такие как fn3()
выше, не должны допускаться. Руководства по стилю C ++ для Google являются примером этого.
Ссылка является псевдонимом для другой переменной, тогда как указатель содержит адрес памяти переменной. Ссылки обычно используются в качестве параметров функции, так что передаваемый объект не является копией, а сам объект.
void fun(int &a, int &b); // A common usage of references.
int a = 0;
int &b = a; // b is an alias for a. Not so common to use.
Возможно, некоторые метафоры помогут; В контексте экрана вашего рабочего стола -
Я всегда решаю это правило из C ++ Core Guidelines:
Предпочитает T * over T & amp; когда «no argument» является допустимым вариантом
blockquote>
nullptr
или использовать терминальные объекты, можно считать гораздо лучшим решением, а не разрешать nullptr
в качестве аргументов.
– Clearer
19 December 2017 в 10:01
Другое отличие состоит в том, что у вас могут быть указатели на тип void (и это означает, что указатель на что-либо), но ссылки на void запрещены.
int a;
void * p = &a; // ok
void & p = a; // forbidden
Я не могу сказать, что я действительно счастлив с этой особой разницей. Я бы предпочел, чтобы это разрешалось со ссылкой на что-либо с адресом и в противном случае такое же поведение для ссылок. Это позволило бы определить некоторые эквиваленты функций библиотеки C, таких как memcpy, используя ссылки.
Существует семантическая разница, которая может казаться эзотерической, если вы не знакомы с изучением компьютерных языков абстрактным или даже академическим способом.
На самом высоком уровне идея ссылок заключается в том, что они прозрачные "псевдонимы". Ваш компьютер может использовать адрес, чтобы заставить их работать, но вы не должны беспокоиться об этом: вы должны думать о них как о «просто другом имени» для существующего объекта, и этот синтаксис отражает это. Они более строгие, чем указатели, поэтому ваш компилятор может более надежно предупредить вас, когда вы собираетесь создать оборванную ссылку, чем когда вы собираетесь создать обвисший указатель.
Кроме того, есть, конечно, некоторые практические различия между указателями и ссылками. Синтаксис для их использования, очевидно, различен, и вы не можете «пересаживать» ссылки, ссылаться на небытие или ссылаться на ссылки.
Вопреки распространенному мнению, возможно иметь ссылку, которая является NULL.
int * p = NULL;
int & r = *p;
r = 1; // crash! (if you're lucky)
Конечно, это гораздо сложнее сделать с ссылкой, но если вы справитесь с ней, вы будете вырвите волосы, пытаясь найти его. Ссылки not неотъемлемо безопасны в C ++!
Технически это недопустимая ссылка, а не нулевая ссылка. C ++ не поддерживает нулевые ссылки как концепцию, как вы можете найти на других языках. Существуют и другие недопустимые ссылки. Любая недопустимая ссылка вызывает призрак неопределенного поведения, так же как и использование недопустимого указателя.
Фактическая ошибка заключается в разыменовании указателя NULL до назначения на Справка. Но я не знаю каких-либо компиляторов, которые будут генерировать любые ошибки при этом условии - ошибка распространяется до точки далее в коде. Вот почему эта проблема настолько коварна. Большую часть времени, если вы разыскиваете указатель NULL, вы ругаетесь прямо в этом месте, и это не требует большой отладки, чтобы понять это.
Мой пример выше короткий и надуманный. Вот еще пример реального мира.
class MyClass
{
...
virtual void DoSomething(int,int,int,int,int);
};
void Foo(const MyClass & bar)
{
...
bar.DoSomething(i1,i2,i3,i4,i5); // crash occurs here due to memory access violation - obvious why?
}
MyClass * GetInstance()
{
if (somecondition)
return NULL;
...
}
MyClass * p = GetInstance();
Foo(*p);
Я хочу повторить, что единственный способ получить нулевую ссылку - это неправильный код, и как только вы его получите, вы получаете неопределенное поведение. Никогда не имеет смысла проверять нулевую ссылку; например, вы можете попробовать if(&bar==NULL)...
, но компилятор может оптимизировать утверждение из существования! Действительная ссылка никогда не может быть NULL, поэтому из представления компилятора сравнение всегда неверно, и можно исключить предложение if
как мертвый код - это сущность неопределенного поведения.
Собственно способ избежать неприятностей - избежать разыменования указателя NULL для создания ссылки. Вот автоматический способ достижения этого.
template<typename T>
T& deref(T* p)
{
if (p == NULL)
throw std::invalid_argument(std::string("NULL reference"));
return *p;
}
MyClass * p = GetInstance();
Foo(deref(p));
Для более старого взгляда на эту проблему у кого-то с лучшими навыками письма см. Null References от Jim Hyslop и Herb Sutter.
Еще один пример опасности разыменования нулевого указателя см. в Предоставление неопределенного поведения при попытке передать код на другую платформу Раймондом Ченом.
Указатель может быть инициализирован равным 0, а ссылка не указана. Фактически ссылка должна также ссылаться на объект, но указатель может быть нулевым указателем:
int* p = 0;
Но мы не можем иметь int& p = 0;
, а также int& p=5 ;
.
На самом деле, чтобы сделать это правильно, мы должны были объявить и определить объект в первом, тогда мы сможем сделать ссылку на этот объект, поэтому правильная реализация предыдущего кода будет:
Int x = 0;
Int y = 5;
Int& p = x;
Int& p1 = y;
Еще один важный момент заключается в том, что мы можем сделать объявление указателя без инициализации, однако в случае ссылки такая вещь не может быть сделана, которая должна всегда ссылаться на переменную или объект. Однако такое использование указателя является рискованным, поэтому мы обычно проверяем, указывает ли указатель на что-то или нет. В случае ссылки такая проверка не требуется, поскольку мы уже знаем, что ссылка на объект во время объявления является обязательной.
Другое отличие заключается в том, что указатель может указывать на другой объект, однако ссылка всегда ссылается на тот же объект, возьмем этот пример:
Int a = 6, b = 5;
Int& rf = a;
Cout << rf << endl; // The result we will get is 6, because rf is referencing to the value of a.
rf = b;
cout << a << endl; // The result will be 5 because the value of b now will be stored into the address of a so the former value of a will be erased
Еще один момент: когда у нас есть шаблон, подобный шаблону STL, такой тип шаблона всегда будет возвращать ссылку, а не указатель, чтобы упростить чтение или присвоение нового значения с помощью оператора []:
Std ::vector<int>v(10); // Initialize a vector with 10 elements
V[5] = 5; // Writing the value 5 into the 6 element of our vector, so if the returned type of operator [] was a pointer and not a reference we should write this *v[5]=5, by making a reference we overwrite the element by using the assignment "="
const &
и только тогда, когда ссылка выходит за пределы области действия деструктора ссылочного типа actual i> (по сравнению с ссылочным типом, который может быть база). Поскольку это ссылка, между ними не будет нарезки.
– David Rodríguez - dribeas
14 January 2010 в 18:06
maybeModify
не принимает адрес чего-либо, связанного с x
, существенно проще, чем доказательство того, что связка арифметики указателя не встречается.
– Cort Ammon
11 September 2013 в 05:27
->
предоставляет ссылки на указатели, так же как и с самим указателем.
– Max Truxa
15 April 2015 в 17:37
nullptr
? Вы действительно читали какую-либо другую часть этой темы или ...?
– underscore_d
11 October 2015 в 17:27
void maybeModify(int& x) { 1[&x]++; }
, о котором говорится в других комментариях выше
– Ben Voigt
4 December 2015 в 00:28
.
лучше, чем использование ->
, но так же, как vi vs emacs, это полностью субъективно, и вы ничего не можете доказать
– Orion Edwards
25 August 2016 в 21:41
Animal x = fast ? getHare() : getTortoise()
, тогда x
столкнутся с проблемой классической резки, а Animal& x = ...
будет работать правильно.
– Arthur Tacca
2 November 2017 в 12:04
Ссылка не является другим именем, данным некоторой памяти. Это неизменный указатель, который автоматически отключается при использовании. В основном это сводится к:
int& j = i;
Он внутренне становится
int* const j = &i;
const
. Эта гибкость не доказывает, что существует разница между ссылкой и указателем.
– Ben Voigt
26 August 2015 в 23:00
Не важно, сколько места оно занимает, так как вы не можете увидеть какой-либо побочный эффект (без выполнения кода) любого пространства, которое потребуется.
С другой стороны, один Основное различие между ссылками и указателями заключается в том, что временные значения, назначенные для ссылок на константу, живут до тех пор, пока константная ссылка не выходит за рамки.
Например:
class scope_test
{
public:
~scope_test() { printf("scope_test done!\n"); }
};
...
{
const scope_test &test= scope_test();
printf("in scope\n");
}
будет печатать:
in scope
scope_test done!
Это языковой механизм, который позволяет ScopeGuard работать.
Рискуя добавить в замешательство, я хочу добавить какой-то ввод, я уверен, что это в основном зависит от того, как компилятор реализует ссылки, но в случае gcc идея о том, что ссылка может указывать только на переменную на стеке на самом деле не правильно, возьмите это, например:
#include <iostream>
int main(int argc, char** argv) {
// Create a string on the heap
std::string *str_ptr = new std::string("THIS IS A STRING");
// Dereference the string on the heap, and assign it to the reference
std::string &str_ref = *str_ptr;
// Not even a compiler warning! At least with gcc
// Now lets try to print it's value!
std::cout << str_ref << std::endl;
// It works! Now lets print and compare actual memory addresses
std::cout << str_ptr << " : " << &str_ref << std::endl;
// Exactly the same, now remember to free the memory on the heap
delete str_ptr;
}
Что выводит это:
THIS IS A STRING
0xbb2070 : 0xbb2070
Если вы заметили, что адреса памяти точно совпадают, ссылка успешно указывает на переменную в куче! Теперь, если вы действительно хотите получить freaky, это также работает:
int main(int argc, char** argv) {
// In the actual new declaration let immediately de-reference and assign it to the reference
std::string &str_ref = *(new std::string("THIS IS A STRING"));
// Once again, it works! (at least in gcc)
std::cout << str_ref;
// Once again it prints fine, however we have no pointer to the heap allocation, right? So how do we free the space we just ignorantly created?
delete &str_ref;
/*And, it works, because we are taking the memory address that the reference is
storing, and deleting it, which is all a pointer is doing, just we have to specify
the address with '&' whereas a pointer does that implicitly, this is sort of like
calling delete &(*str_ptr); (which also compiles and runs fine).*/
}
Что выводит это:
THIS IS A STRING
Поэтому ссылка является указателем под капотом, они оба являются просто сохранение адреса памяти, в котором указывает адрес, не имеет значения, что, по вашему мнению, произойдет, если я вызову std :: cout & lt; & lt; str_ref; ПОСЛЕ вызова delete & amp; str_ref? Ну, очевидно, что он компилируется нормально, но вызывает ошибку сегментации во время выполнения, потому что он больше не указывает на допустимую переменную, мы по существу имеем сломанную ссылку, которая все еще существует (пока она не выпадает из области), но бесполезна.
Другими словами, ссылка - это не что иное, как указатель, у которого механики указателей отвлечены, что делает его более безопасным и простым в использовании (без случайной математики указателя, без смешивания «.» и «->» и т. д.). , предполагая, что вы не пробовали какую-либо глупость, как мои примеры выше;)
Теперь, независимо от того, как компилятор обрабатывает ссылки, он всегда будет иметь какой-то указатель под капотом, потому что ссылка должна ссылаться на конкретную переменную в определенном адресе памяти, чтобы она работала так, как ожидалось, не обойти это (отсюда и термин «ссылка»).
Единственное важное правило, которое важно запомнить с помощью ссылок, заключается в том, что они должны определяется во время объявления (за исключением ссылки в заголовке, в этом случае это должно быть определено ined in the constructor, после того, как объект, в который он содержится, построен слишком поздно, чтобы определить его).
Помните, что мои примеры выше - это просто примеры, демонстрирующие, что такое ссылка, вы никогда не захотите использовать ссылка в этом смысле! Для правильного использования ссылки здесь уже много ответов, которые поражают гвоздь на голове
Обе ссылки и указатели могут использоваться для изменения локальных переменных одной функции внутри другой функции. Оба они могут также использоваться для сохранения копирования больших объектов при передаче в качестве аргументов функций или возврата из функций, чтобы получить коэффициент усиления эффективности. Несмотря на вышеописанные сходства, существуют следующие различия между ссылками и указателями.
Ссылки менее эффективны, чем указатели
1) После создания ссылки впоследствии нельзя ссылаться на другой объект ; он не может быть пересмотрен. Это часто делается с указателями.
2) Ссылки не могут быть NULL. Указатели часто делают NULL, чтобы указать, что они не указывают на какую-либо действительную вещь.
3) Ссылка должна быть инициализирована при объявлении. Нет такого ограничения с указателями
Из-за вышеуказанных ограничений ссылки в C ++ не могут использоваться для реализации структур данных, таких как Linked List, Tree и т. Д. В Java ссылки не указаны выше ограничений и может использоваться для реализации всех структур данных. Ссылки, более мощные в Java, являются основной причиной, по которой Java не нуждается в указателях.
Ссылки более безопасны и удобны в использовании:
1) Безопаснее: поскольку ссылки должны быть инициализированы, дикие ссылки, такие как дикие указатели, вряд ли будут существовать. Все еще возможно иметь ссылки, которые не относятся к допустимому местоположению
2) Легче использовать: для доступа к значению не требуется оператор разыменования. Они могут использоваться как обычные переменные. Оператор '& amp;' необходим только во время объявления. Кроме того, к элементам ссылки объекта можно обращаться с помощью оператора точек ('.'), В отличие от указателей, где для доступа к элементам необходим оператор стрелки (->).
Вместе с вышеуказанными причинами, существует несколько мест, таких как аргумент конструктора копирования, где указатель нельзя использовать. Ссылка должна использоваться, чтобы передать аргумент в конструкторе копирования. Аналогичным образом ссылки должны использоваться для перегрузки некоторых операторов, таких как ++.
Разница заключается в том, что переменная указателя константы (не путать с указателем на константу) может быть изменена в какое-то время во время выполнения программы, требуется использовать семантику указателя (& amp;, *), а ссылки могут устанавливаются только при инициализации (поэтому вы можете устанавливать их только в списке инициализаторов конструктора, но не как-то иначе) и использовать обычную доступность для семантики. В основном были введены ссылки, позволяющие поддерживать перегрузку операторов, как я читал в какой-то очень старой книге. Как кто-то сказал в этом потоке - указатель может быть установлен в 0 или любое другое значение, которое вы хотите. 0 (NULL, nullptr) означает, что указатель инициализирован ничем. Это ошибка для разыменования нулевого указателя. Но на самом деле указатель может содержать значение, которое не указывает на правильное расположение памяти. В свою очередь, ссылки не позволяют пользователю инициализировать ссылку на то, на что нельзя ссылаться, из-за того, что вы всегда предоставляете ему значение правильного типа. Хотя есть много способов сделать ссылочную переменную инициализированной неправильной ячейкой памяти - вам лучше не углубляться в детали. На уровне машины оба указателя и ссылки работают равномерно - с помощью указателей. Скажем, в основных ссылках речь идет о синтаксическом сахаре. Ссылки rvalue отличаются от этого - они, естественно, представляют собой объекты stack / heap.
Хотя обе ссылки и указатели используются для косвенного доступа к другому значению, существуют два важных различия между ссылками и указателями. Во-первых, ссылка всегда ссылается на объект: ошибка заключается в определении ссылки без ее инициализации. Поведение присвоения - это второе важное различие: Присвоение ссылки заменяет объект, к которому привязана ссылка; он не перепроверяет ссылку на другой объект. После инициализации ссылка всегда относится к одному и тому же базовому объекту.
Рассмотрим эти два фрагмента программы. В первом мы назначаем один указатель на другой:
int ival = 1024, ival2 = 2048;
int *pi = &ival, *pi2 = &ival2;
pi = pi2; // pi now points to ival2
После назначения ival объект, адресуемый pi, остается неизменным. Назначение изменяет значение pi, указывая на другой объект. Теперь рассмотрим аналогичную программу, которая присваивает две ссылки:
int &ri = ival, &ri2 = ival2;
ri = ri2; // assigns ival2 to ival
Это присваивание изменяет значение ival, значение, на которое ссылается ri, а не сама ссылка. После назначения две ссылки по-прежнему относятся к их исходным объектам, и значение этих объектов теперь тоже самое.
Я использую ссылки, если мне не требуется ни одно из них:
p += offset;
const &
и только тогда, когда ссылка выходит за пределы области действия деструктора ссылочного типа actual i> (по сравнению с ссылочным типом, который может быть база). Поскольку это ссылка, между ними не будет нарезки.
– David Rodríguez - dribeas
14 January 2010 в 18:06
maybeModify
не принимает адрес чего-либо, связанного с x
, существенно проще, чем доказательство того, что связка арифметики указателя не встречается.
– Cort Ammon
11 September 2013 в 05:27
->
предоставляет ссылки на указатели, так же как и с самим указателем.
– Max Truxa
15 April 2015 в 17:37
nullptr
? Вы действительно читали какую-либо другую часть этой темы или ...?
– underscore_d
11 October 2015 в 17:27
void maybeModify(int& x) { 1[&x]++; }
, о котором говорится в других комментариях выше
– Ben Voigt
4 December 2015 в 00:28
.
лучше, чем использование ->
, но так же, как vi vs emacs, это полностью субъективно, и вы ничего не можете доказать
– Orion Edwards
25 August 2016 в 21:41
Animal x = fast ? getHare() : getTortoise()
, тогда x
столкнутся с проблемой классической резки, а Animal& x = ...
будет работать правильно.
– Arthur Tacca
2 November 2017 в 12:04