Следующий код не компилируется.
int a = 1, b = 2, c = 3;
int& arr[] = {a,b,c,8};
Что стандарт C ++ говорит об этом?
Я знаю, что мог бы объявить класс, который содержит ссылку, а затем создать массив этого класса, как показано ниже. Но я действительно хочу знать, почему приведенный выше код не компилируется.
struct cintref
{
cintref(const int & ref) : ref(ref) {}
operator const int &() { return ref; }
private:
const int & ref;
void operator=(const cintref &);
};
int main()
{
int a=1,b=2,c=3;
//typedef const int & cintref;
cintref arr[] = {a,b,c,8};
}
Можно использовать struct cintref
вместо того, const int &
чтобы моделировать массив ссылок.
intlink value = 8;
работает. проверь если не веришь.operator=
. Ссылки не могут быть пересмотрены. Если вы действительно хотите , такую семантику - хотя я лично не нашел ситуацию , в которой они практически полезны - тогдаstd::reference_wrapper
бы способ сделать это, так как он на самом деле хранит указатель , но предоставляет ссылки, какoperator
с и это позволяет переустановка. Но тогда я бы просто использовал указатель!Ответы:
Отвечая на ваш вопрос о стандарте, я могу привести C ++ Standard §8.3.2 / 4 :
источник
struct
единственный элемент, ссылка которого является ссылкой. Но затем, таким образом, теперь у вас есть и ссылка, и родительский объект для имени ... что теперь означает, что вы можете однозначно указать, какой адрес вы хотите. Кажется очевидным ... так почему никто не сказал это?What more is there to say?
Обоснование почему ? Я все о Стандарте, но просто цитирую его и предполагаю, что это конец дискуссии, похоже на безошибочный способ уничтожить критическую мысль пользователей - наряду с любым потенциалом для развития языка, например, за пределами ограничений пропусков или искусственное ограничение. Слишком много, потому что Стандарт говорит «здесь - и недостаточно», и это очень разумно сказать по следующим практическим причинам ». Я не знаю, почему возражения так охотно идут на ответы, которые говорят только о первом, даже не пытаясь исследовать второе.Ссылки не являются объектами. У них нет собственного хранилища, они просто ссылаются на существующие объекты. По этой причине не имеет смысла иметь массивы ссылок.
Если вы хотите легкий объект который ссылается на другой объект, вы можете использовать указатель. Вы сможете использовать объект
struct
со ссылочным элементом в качестве объектов в массивах только в том случае, если вы предоставите явную инициализацию для всех ссылочных элементов для всехstruct
экземпляров. Ссылки не могут быть инициализированы по умолчанию.Редактировать: Как отмечает jia3ep, в стандартном разделе объявлений есть явный запрет на массивы ссылок.
источник
Это интересная дискуссия. Ясно, что массивы ссылок совершенно незаконны, но ИМХО причина, почему не так просто сказать «они не объекты» или «они не имеют размера». Я хотел бы отметить, что сами массивы не являются полноценными объектами в C / C ++ - если вы возражаете против этого, попробуйте создать экземпляр некоторых классов шаблонов stl, используя массив в качестве параметра шаблона 'class', и посмотрите, что произойдет. Вы не можете вернуть их, назначить их, передать их в качестве параметров. (параметр массива рассматривается как указатель). Но допустимо создавать массивы из массивов. Ссылки имеют размер, который компилятор может и должен рассчитать - вы не можете использовать sizeof () для ссылки, но вы можете создать структуру, не содержащую ничего, кроме ссылок. Он будет иметь размер, достаточный для размещения всех указателей, которые реализуют ссылки. Ты можешь'
На самом деле вы можете добавить эту строку в определение структуры
... и теперь у меня есть кое-что, что выглядит много как массив ссылок:
Теперь это не настоящий массив, это перегрузка оператора; он не будет делать то, что обычно делают массивы, например, sizeof (arr) / sizeof (arr [0]). Но он делает именно то, что я хочу, чтобы массив ссылок делал с совершенно легальным C ++. За исключением (а) неудобно устанавливать более 3 или 4 элементов, и (б) он выполняет вычисления с использованием нескольких символов?: Что можно сделать с помощью индексации (а не с помощью обычной индексации семантики C-указателя-вычисления-семантики) , но индексация тем не менее). Я хотел бы видеть очень ограниченный тип «массив ссылок», который действительно может сделать это. Т.е. массив ссылок не будет рассматриваться как общий массив вещей, которые являются ссылками, а скорее будет новым «массивом ссылок» сделать с шаблонами).
это, вероятно, сработает, если вы не возражаете против такого рода мерзостей: переделайте '* this' в массив int * и верните ссылку, сделанную из одного: (не рекомендуется, но показывает, как правильно 'array' должно сработать):
источник
std::tuple<int&,int&,int&> abcref = std::tie( a,b,c)
- который создает «массив» ссылок, который может быть проиндексирован только константами времени компиляции с использованием std :: get. Но ты не можешь сделатьstd::array<int&,3> abcrefarr = std::tie( a,b,c)
. Может быть, есть способ сделать это, о котором я не знаю. Мне кажется, что должен быть способ написать специализацию,std::array<T&,N>
которая может сделать это - и, таким образом, функцию,std::tiearray(...)
которая возвращает один такой (или позволяетstd::array<T&,N>
принять инициализатор, содержащий адреса = {& v1, & v2 и т. Д.})?:
std::array<T,N>
, легко определяемый в коде приложения, не был добавлен в std :: до c ++ 11, предположительно потому, что было бы странно иметь это без способа Это= {1,2,3};
был «языковой взлом»?Комментарий к вашему редактированию:
Лучшее решение есть
std::reference_wrapper
.Подробности: http://www.cplusplus.com/reference/functional/reference_wrapper/
Пример:
источник
reference_wrapper
.Массив неявно преобразуется в указатель, а указатель на ссылку недопустим в C ++
источник
Учитывая
int& arr[] = {a,b,c,8};
, что этоsizeof(*arr)
?Повсюду в другом месте ссылка рассматривается как просто сама вещь, так
sizeof(*arr)
должно бытьsizeof(int)
. Но это сделало бы арифметику указателя массива в этом массиве неправильной (при условии, что ссылки не совпадают по ширине с точностью до целого). Чтобы устранить двусмысленность, это запрещено.источник
struct
чьим единственным участником является эта ссылка и узнай ..?Потому что, как многие уже говорили здесь, ссылки не являются объектами. они просто псевдонимы. Правда, некоторые компиляторы могут реализовывать их как указатели, но стандарт не заставляет / не указывает это. А поскольку ссылки не являются объектами, вы не можете на них указывать. Хранение элементов в массиве означает, что существует некоторый индексный адрес (т. Е. Указывающий на элементы с определенным индексом); и именно поэтому у вас не может быть массивов ссылок, потому что вы не можете на них указывать.
Используйте вместо него boost :: reference_wrapper или boost :: tuple; или просто указатели.
источник
Я считаю, что ответ очень прост и связан с семантическими правилами ссылок и с тем, как обрабатываются массивы в C ++.
Вкратце: Ссылки можно рассматривать как структуры, которые не имеют конструктора по умолчанию, поэтому применяются все те же правила.
1) Семантически ссылки не имеют значения по умолчанию. Ссылки могут быть созданы только путем ссылки на что-то. Ссылки не имеют значения для представления отсутствия ссылки.
2) При выделении массива размера X программа создает коллекцию инициализированных по умолчанию объектов. Поскольку ссылка не имеет значения по умолчанию, создание такого массива семантически недопустимо.
Это правило также применяется к структурам / классам, которые не имеют конструктора по умолчанию. Следующий пример кода не компилируется:
источник
Object
, вы просто должны убедиться , чтобы инициализировать их всех:Object objects[1] = {Object(42)};
. Между тем, вы не можете создать массив ссылок, даже если вы инициализируете их все.Вы можете довольно близко подобраться к этой структуре шаблона. Однако вам нужно инициализировать с помощью выражений, которые указывают на T, а не на T; и поэтому, хотя вы можете легко сделать «fake_constref_array» аналогичным образом, вы не сможете привязать это к значениям, как это сделано в примере OP ('8');
-> A = 0 B = 7 X = {0,8,0}
источник
Ссылочный объект не имеет размера. Если вы напишите
sizeof(referenceVariable)
, он даст вам размер объекта, на который ссылаетсяreferenceVariable
, а не размер самой ссылки. Он не имеет собственного размера, поэтому компилятор не может рассчитать, какой размер потребуется массиву.источник
Когда вы сохраняете что-либо в массиве, его размер должен быть известен (поскольку индексирование массива зависит от размера). В соответствии со стандартом C ++ Не указано, требуется ли ссылка для хранения, в результате индексирование массива ссылок будет невозможно.
источник
struct
, волшебным образом все становится определенным, четко определенным, гарантированным и имеющим детерминированный размер. Почему же существует эта, казалось бы, полностью искусственная разница?struct
дает обертка , начинают предлагать себя некоторые хорошие возможные ответы - но мне, никто еще этого не сделал, несмотря на то, что это является одной из непосредственных проблем для всех общих обоснование того, почему вы не можете использовать развернутые ссылки.Просто чтобы добавить ко всему разговору. Поскольку массивы требуют последовательных расположений памяти для хранения элемента, поэтому, если мы создадим массив ссылок, то не гарантируется, что они будут находиться в последовательном расположении памяти, поэтому доступ будет проблемой, и, следовательно, мы не можем даже применить все математические операции к массив.
источник
Рассмотрим массив указателей. Указатель - это действительно адрес; поэтому, когда вы инициализируете массив, вы аналогично говорите компьютеру: «выделите этот блок памяти для хранения этих чисел X (которые являются адресами других элементов)». Затем, если вы меняете один из указателей, вы просто меняете то, на что он указывает; это все еще числовой адрес, который сам находится в том же месте.
Ссылка аналогична псевдониму. Если бы вы объявляли массив ссылок, вы бы в основном говорили компьютеру: «выделите этот аморфный шарик памяти, состоящий из всех этих разных предметов, разбросанных вокруг».
источник
struct
единственного члена, являющегося эталоном, приводит к чему-то совершенно законному, предсказуемому и неаморфному? Почему пользователь должен обернуть ссылку, чтобы он мог волшебным образом получить способности с поддержкой массивов, или это просто искусственное ограничение? ИМО без ответа напрямую обратился к этому. Я предполагаю, что опровержение: «Объект обертки гарантирует, что вы можете использовать семантику значений в форме объекта обертывания, поэтому он гарантирует, что вы можете иметь гарантии значений, которые необходимы, например, как, например, можно устранить неоднозначность между элементом и адресом рефери» ... Это то, что вы имели в виду?На самом деле, это смесь синтаксиса C и C ++.
Вы должны либо использовать чистые массивы C, которые не могут быть ссылками, поскольку ссылки являются частью только C ++. Или вы идете по пути C ++ и используете
std::vector
илиstd::array
класс для своих целей.Что касается редактируемой части: несмотря на то, что
struct
это элемент из C, вы определяете конструктор и операторные функции, которые делают его C ++class
. Следовательно, вашstruct
не будет компилироваться в чистом C!источник
std::vector
илиstd::array
не может содержать ссылки либо. Стандарт C ++ совершенно ясен, что ни один контейнер не может.