LINUX.ORG.RU

Ссылки и типы в C++

 , ,


0

4

Заинтересовал что-то меня вопрос о том, зачем было делать ссылки частью системы типов. Фактически они работают как синонимы, не могут храниться в массивах и пр. и пр. Я уже не говорю о привнесенной в язык сложности, которую усиливает новый стандарт посредством rvalue-ссылок.

При этом появились ссылки исключительно ради перегрузки операторов, т.к. указатели не позволяли это сделать. Если верить D&E.

Не лучше ли было сделать механизм квалификаторов для «синонимов»(что-то вроде ref в C#, только с учетом константности), чтобы программист мог указывать, что функция принимает аргумент/возвращает значение по ссылке, а не по значению. Проблему перегрузки операторов это решает полностью, сложности никакой не представляет, систему типов не усложняет.



Последнее исправление: CYB3R (всего исправлений: 1)

Ответ на: комментарий от dzidzitop

Я его запретил (он приведёт к exception).

Он приведет к ошибке компиляции. Причем даже если бы ты его не запретил, он бы тоже к ней привел.

Он всегда подошёл бы, разница только в том, что T& обозначает что-то конкретное, а не просто адрес участка памяти.

        struct UnlockGuard
        {
                UnlockGuard(ref mutex mutex) : m_mutex(&mutex) { m_mutex->lock(); };
                ~UnlockGuard() { m_mutex->unlock(); }
        private:
                UnlockGuard(ref const UnlockGuard) = delete;
                ref UnlockGuard operator=(ref const UnlockGuard) = delete;

                mutex *m_mutex;
        };
forCe
() автор топика
Ответ на: комментарий от emulek

Слушай, это не важно. И не имеет отношения к вопросу. Ссылка «объявлена» отдельным типом, но при этом им не является. Я просто решил узнать, не писал ли об этом Страуструп или еще кто-то.

forCe
() автор топика
Ответ на: комментарий от forCe

Это при том что возможность иметь копии UnlockGuard приведёт к undefined behaviour. Так что ошибка компиляции (и потому что private и потому что = delete) есть добром.

Про то что T& технически не необходимы - согласен.

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

Так что ошибка компиляции (и потому что private и потому что = delete) есть добром.

Там ошибка компиляции на присваивании будет и без private и delete. Ссылки-то нельзя присваивать. В твоем конкретном примере это правильно. В общем случае не очень=)

forCe
() автор топика
Ответ на: комментарий от forCe

Stroustrup:

A reference is an alternative name for an object, an alias. The main use of references is for specifying arguments and return values for functions in general and for overloaded operators (Chapter 18) in particular. For example:

....

The idea of passing function arguments by reference is as old as high-level programming languages (the first version of Fortran used that). To reflect the lvalue/rvalue and const/non-const distinctions, there are three kinds of references:

dzidzitop ★★
()
Ответ на: комментарий от forCe

Важней выразить семантику самого класса, а не то что внутри ссылка которую можно только инициализировать. Тут всё работает гармонично.

В случаях где UnlockGuard может поменять своего «питомца» ссылки работать не будут и будут заменены на *.

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

Ага. В том-то и дело, что он говорит скорее о ref. И в других языках «передача по ссылке» не меняет тип. Это именно способ передачи...

forCe
() автор топика
Ответ на: комментарий от forCe

Вдобавок:

The obvious implementation of a reference is as a (constant) pointer that is dereferenced each time it is used. It doesn’t do much harm to think about references that way, as long as one remembers that a reference isn’t an object that can be manipulated the way a pointer is:

In some cases, the compiler can optimize away a reference so that there is no object representing that reference at run time.

dzidzitop ★★
()
Ответ на: комментарий от forCe

в принципе так. Только в C++ переменную можно об'явить только так: <type> <name>

& не может быть частью имени, так что это есть частью типа. Это рождает некоторую неоднозначность в связке с overloading & template instantiation - но так выглядит согласованно.

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

Именно. И все это можно сказать и о ref...

forCe
() автор топика
Ответ на: комментарий от dzidzitop

Только в C++ переменную можно об'явить только так: <type> <name>

& не может быть частью имени, так что это есть частью типа

Это так, да... Но не проще ли было ввести новый вид объявления, чем вот так вот делать?.. Это все-равно не полноценный тип, да еще и & меняет концепцию Си о сложных объявлениях(значки *, (), [] ставятся на том же месте, где будут стоять при использовании переменных для получения значения «вложенного» типа). В общем, мне кажется решение сомнительным, а его обоснования я не нашел.

forCe
() автор топика
Ответ на: комментарий от encyrtid

Наоборот, ref юзается для того чтобы можно было изменить переданную ссылку.

Ну не наоборот, а скорее не совсем. Для value типов ведь оно иначе работает. Хотя, наверное, «проблема» в том, что я подхожу с точки зрения С++ с его const, которого мне не хватает. Ведь не иммутабельные классы можно модифицировать и без рефа:

class Test
{
  public Test(int v)
  {
    a = v;
  }

  public int a;
}

static void f1(Test t)
{
  t.a = 10;
}
  
static void f2(ref Test t)
{
  t = new Test(10);
}

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Для value типов ведь оно иначе работает

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

encyrtid ★★★★★
()
Ответ на: комментарий от forCe

Слушай, это не важно. И не имеет отношения к вопросу. Ссылка «объявлена» отдельным типом, но при этом им не является. Я просто решил узнать, не писал ли об этом Страуструп или еще кто-то.

не. Ты — первый.

emulek
()
Ответ на: комментарий от emulek

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

forCe
() автор топика
Ответ на: комментарий от emulek

Ты — первый

Судя по тому, что ни в одном другом языке подобных типов нет... А в том же более новом шарпе есть ref, который используется для схожих целей, если речь идет не о классах. Это может означать, что этот эксперимент C++ не прижился.

forCe
() автор топика
Ответ на: комментарий от forCe

Судя по тому, что ни в одном другом языке подобных типов нет...

в других ЯП нет и совместимости с сишечкой. А в C++ есть. И это именно совместимость, а не как в JS&PHP — похожий синтаксис.

emulek
()
Ответ на: комментарий от emulek

Я думаю, что тебе пора бросать привычку говорить не по теме. Между int& и ref int нет никакой разницы в плане совместимости с Си.

forCe
() автор топика
Ответ на: комментарий от forCe

Напиши страўструпу. Может ответит почему & это новый тип. :)

dzidzitop ★★
()
Ответ на: комментарий от forCe

Я думаю, что тебе пора бросать привычку говорить не по теме. Между int& и ref int нет никакой разницы в плане совместимости с Си.

ещё раз повторю, что я не знаю сишарп. Объясни пожалуйста, что должна вернуть функция, которая ref? И как она вообще выглядит в коде x86? Так же? А тогда в чём же твой вопрос, если это то же самое?

emulek
()
Ответ на: комментарий от emulek

Да плевать на си шарп. Вопрос лишь в том, делать ссылки типом и зачем.

И как она вообще выглядит в коде x86? Так же?

Да, так же, как и int&.

А тогда в чём же твой вопрос, если это то же самое?

В том, чтобы не считать ссылку типом. Посмотри мой пример с шаблонами и передачей аргументов. Это маразм какой-то.

forCe
() автор топика

Since a variable reference points to the same location during its entire life, a C++ compiler can do a better job of optimization than it can with pointer-based code.

ckotinko ☆☆☆
()
Ответ на: комментарий от ckotinko

Я вот понять все не могу, почему это все воспринимается как критика С++? Это не критика, мне просто интересно=)

forCe
() автор топика
Ответ на: комментарий от forCe

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

ckotinko ☆☆☆
()
Ответ на: комментарий от forCe

В том, чтобы не считать ссылку типом.

не считай.

Посмотри мой пример с шаблонами и передачей аргументов. Это маразм какой-то.

сахарок...

emulek
()
Ответ на: комментарий от emulek

не. Ты — первый.

Проблевался. Так пишут только мудаки.

anonymous
()
Ответ на: комментарий от emulek

Да он, мудак, везде так пишет. Начинает предложение с прописной, зато тире длинное, сука, не забывает ставить.

Ты же и есть тот умственно отсталый drBatty? Тогда все понятно.

anonymous
()
Ответ на: комментарий от anonymous

То есть со строчной. Ну и мудак этот drBatty.

anonymous
()
Ответ на: комментарий от encyrtid

Value-типы при передаче в функцию копируются

Это мне известно.

DarkEld3r ★★★★★
()
Ответ на: комментарий от ckotinko

ссылки уже есть, смиритесь

Но мне интересно, почему были приняты те или иные решения при создании тех или иных штук, в том числе и языков программирования.

а зачем это все писать если можно не писать?

Для этого не обязательно делать ссылки типом. Вполне достаточно соглашения для «синонимов». Я же писал уже

forCe
() автор топика
Ответ на: комментарий от forCe

Но мне интересно, почему были приняты те или иные решения при создании тех или иных штук, в том числе и языков программирования.

Взял бы и спросил Страуструпа, тем тут срачъ устраивать.

Pavval ★★★★★
()
Ответ на: комментарий от anonymous

от умственно отсталый drBatty? Тогда все понятно.

на мясокомбинате я работаю свиньёй.

emulek
()

В D, видимо, как раз ref не является частью типа: functions.

ref int foo() {
  auto p = new int;
  return *p;
}
...
foo() = 3;  // reference returns can be lvalues

void def(ref int x) {
  x += 1;
}

int z = 3;
def(z);
// z is now 4
forCe
() автор топика
Ответ на: комментарий от anonymous

детка, у тебя опять обострение? Зафренди меня.

emulek
()
Ответ на: комментарий от forCe

Типом ее считает язык С++.

в каком смысле «считает»? Тебе же кинули мнение Страуструпа, какая буква тебе не понятна?

emulek
()
Ответ на: комментарий от emulek

Страуструп говорит о том, зачем нужны ссылки и что они из себя представляют. Там нет ни слова про то, зачем он их сделал типами(а он сделал). Тут выше есть код на D. Надеюсь, такие языки когда-нибудь заменят С++.

anonymous
()
Ответ на: комментарий от forCe

Во мнении Страуструпа нет ни слова о том, почему ссылки в С++ являются типами.

ну ты ведь сам выше доказал, что ссылки в C++ типами НЕ являются. Как и например массивы. Это «специальные формы C++». Они «типы» только на первый взгляд.

Причины, почему так, я тебе объяснил. Да и сам Страуструп — тоже. Ты сказал, что «я знаю, почему так». В чём же твой вопрос состоит?

emulek
()
Ответ на: комментарий от forCe

А зачем нужен такой typedef?

std::vector<T>::reference, например, для T не равного bool это T&, а для равного это специальный класс.

Благодаря тому, что ссылка — это тип, который можно использовать в параметрах шаблона и typedef, можно писать свои классы, имитирующие поведение ссылки, но выполняющие дополнительную работу, и прозрачно их использовать.

xeiph
()
Ответ на: комментарий от emulek

Твоё понимание слова «тип» не совпадает с определением в стандарте C++. По стандарту и типы, и массивы — всё это типы. А ты, похоже, считаешь типами только конкретное расположение байт в памяти.

xeiph
()
Ответ на: комментарий от xeiph

Твоё понимание слова «тип» не совпадает с определением в стандарте C++. По стандарту и типы, и массивы — всё это типы. А ты, похоже, считаешь типами только конкретное расположение байт в памяти.

это не моё, это ТСа, его, как он говорит «полноценные типы». Вот он хоче6т такую «ссылку», у которой можно спросить её адрес, и тогда, по его словам, она будет «полноценным типом».

А мне достаточно того, что есть в стандарте.

emulek
()
Ответ на: комментарий от xeiph

Плохой пример, ибо std::vector<bool> является общепризнанной ошибкой проектирования. Он даже требования стандарта к контейнером не выполняет.

можно писать свои классы, имитирующие поведение ссылки, но выполняющие дополнительную работу, и прозрачно их использовать.

Нельзя. Для этого бы потребовалась перегрузка operator.(обсуждалось в D&E)

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.