Ссылки и указатели
От: x-code  
Дата: 27.06.19 19:32
Оценка: 4 (1)
Существует два синтаксических подхода к доступу к объектам, созданным динамически (в куче): через ссылки и через указатели. Обращение через ссылку неотличимо от непосредственного обрашения к объекту, обращение через указатель явно отличается (присутствует явное разыменование).

В C# и Java используются ссылки, при этом введено соглашение что все объекты классов передаются по ссылке, а структуры и переменные примитивных типов — по значению. Там невозможно создать класс не стеке.

В C, Go, Rust используются явные указатели и явное размыенование. То есть синтаксис косвенного обращения — через указатель — всегда отличается от синтаксиса прямого обращения к стековому или глобальному объекту. В С++ сосуществуют и указатели и ссылки, причем поведение ссылок отличается от такового в C#.

В чем по-вашему преимущества и недостатки обоих подходов? Что лучше — явность (однозначно виден способ передачи объекта в функцию, способ обращения к нему и т.д.) или унификация доступа (везде точка, никаких разыменований)? Какой подход вам больше нравится? Правильно ли то, что в С++ сосуществуют оба способа, почему так сложилось, дает ли это какие-то преимущества и создает ли это какие-либо проблемы?
Re: Ссылки и указатели
От: Mystic Artifact  
Дата: 27.06.19 19:50
Оценка:
Здравствуйте, x-code, Вы писали:

XC>В чем по-вашему преимущества и недостатки обоих подходов?

Ни в чем: механически это один и тот же маханизм. Отличия в синтаксисе и возлагаемой в C++ на ссылки семантике.

XC>Правильно ли то, что в С++ сосуществуют оба способа, почему так сложилось, дает ли это какие-то преимущества и создает ли это какие-либо проблемы?

Думаю правильно, хотя синтаксис, хоть и уже привычен, тем не менее не радует.
В C# т.н. семантика типа (ссылочная/значимый) связана с самим типом, а в C++ все типы значимые, с возможностью превратить его в ссылку (кое-какая работа с указателями в C# слава богу есть), строго говоря это отдельный тип.
Так вот, мне видится, что гораздо удобнее иметь весь арсенал в своем расположении, а не городить костыли вокруг урезанных возможностей.
В жизни, мы как раз и хотим иногда рассматривать один и тот же тип то как значение, то оперировать ссылкой на него, а иногда и вовсе прибегнуть к обычным указателям (хотя ссылка/указатель здесь все же про C++, я могу представить язык в котором это объединено). Тем не менее, возможно, иметь в наличие обычные старые указатели это хорошо, просто с точки зрения что они привычны и понятны большому числу людей.
Re: Ссылки и указатели
От: 0x7be СССР  
Дата: 27.06.19 19:54
Оценка: +1
Здравствуйте, x-code, Вы писали:

XC>В чем по-вашему преимущества и недостатки обоих подходов? Что лучше — явность (однозначно виден способ передачи объекта в функцию, способ обращения к нему и т.д.) или унификация доступа (везде точка, никаких разыменований)? Какой подход вам больше нравится? Правильно ли то, что в С++ сосуществуют оба способа, почему так сложилось, дает ли это какие-то преимущества и создает ли это какие-либо проблемы?

Указатели — это гибкость, ссылки — безопасность (относительная).
В остальном — чисто синтаксическая вкусовщина.
Re: Ссылки и указатели
От: Mystic Artifact  
Дата: 27.06.19 19:57
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Что лучше — явность (однозначно виден способ передачи объекта в функцию, способ обращения к нему и т.д.) или унификация доступа (везде точка, никаких разыменований)?

Забыл добавить, я бы предпочел везде точку, но если есть понятие указателя — тогда стрелку. Сигнатура должна быть понятной (явной).
А вот, если, компилятор/язык сможет сам решать где нужно передавать по ссылке или по значению — тогда неявно.
В тоже время, мне жутко не нравятся доброусыпанные крючки, и опыт шарпа показывает, что здесь вполне возможен разумный компромис. Т.е., если бы был хороший и удобный вариант передачи этого неявно с возможностью указать явно — это было бы интересно.
Re: Ссылки и указатели
От: Zhendos  
Дата: 27.06.19 20:59
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Существует два синтаксических подхода к доступу к объектам, созданным динамически (в куче): через ссылки и через указатели. Обращение через ссылку неотличимо от непосредственного обрашения к объекту, обращение через указатель явно отличается (присутствует явное разыменование).


XC>В C# и Java используются ссылки, при этом введено соглашение что все объекты классов передаются по ссылке, а структуры и переменные примитивных типов — по значению. Там невозможно создать класс не стеке.


XC>В C, Go, Rust используются явные указатели и явное размыенование.


Ну по крайней мере для Rust это не так.
В Rust есть и ссылки и указатели.
fn f(x: *mut i32) {} // указатель
fn f(x: &mut i32) {} // ссылка
Re: Ссылки и указатели
От: Pzz Россия https://github.com/alexpevzner
Дата: 27.06.19 22:45
Оценка: +1
Здравствуйте, x-code, Вы писали:

XC>В C, Go, Rust используются явные указатели и явное размыенование. То есть синтаксис косвенного обращения — через указатель — всегда отличается от синтаксиса прямого обращения к стековому или глобальному объекту. В С++ сосуществуют и указатели и ссылки, причем поведение ссылок отличается от такового в C#.


В Go для доступа к полю структуры всегда используется точка, независимо от того, что стоит слева от точки: имя переменной-структуры, или указатель на структуру.

XC>В чем по-вашему преимущества и недостатки обоих подходов? Что лучше — явность (однозначно виден способ передачи объекта в функцию, способ обращения к нему и т.д.) или унификация доступа (везде точка, никаких разыменований)? Какой подход вам больше нравится? Правильно ли то, что в С++ сосуществуют оба способа, почему так сложилось, дает ли это какие-то преимущества и создает ли это какие-либо проблемы?


На мой взгляд, какого-нибудь одного способа вполне бы хватило. Проблема C++ в том, что из него ничего нельзя выкинуть из-за совместимости со всеми предшествующими версиями данного языка.
Re: Ссылки и указатели
От: B0FEE664  
Дата: 28.06.19 13:03
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Существует два синтаксических подхода к доступу к объектам, созданным динамически (в куче): через ссылки и через указатели.

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

XC>Обращение через ссылку неотличимо от непосредственного обрашения к объекту, обращение через указатель явно отличается (присутствует явное разыменование).

Общее положение дел несколько сложнее. Вообще говоря ссылка от указателя отличается только тем, что указатель можно сравнить с нуль-объектом. Это все различия.

XC>В чем по-вашему преимущества и недостатки обоих подходов?

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

XC>Что лучше — явность (однозначно виден способ передачи объекта в функцию, способ обращения к нему и т.д.) или унификация доступа (везде точка, никаких разыменований)?

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

XC>Какой подход вам больше нравится? Правильно ли то, что в С++ сосуществуют оба способа, почему так сложилось, дает ли это какие-то преимущества и создает ли это какие-либо проблемы?


В С++ ситуация намного сложнее описываемой дихотомии сразу по многим аспектам.
Во-первых, С++ может использоваться для прямого доступа к памяти по физическому адресу. Это обеспечивается с помощью указателей (хотя можно придумать и другой способ, если иметь возможность размещать обычную переменную по заданному адресу) и это объясняет наличие указателей в языке.
Во-вторых, в С++ есть арифметика на указателях, которая непосредственно связана с предыдущем пунктом.
В-третьих, идеологически голые указатели в С++ не нужны, кроме как для доступа по физическим адресам. Во всех других случаях достаточно использовать объекты, например, типа "Умные указатели", которые по некоторым признакам не указатели, а объекты.
В-четвёртых, доступ по '.' через '->' — это доступ с помощью операторов и оператор '->' может применятся к обычному объекту, а не указателю.
  Скрытый текст
class A
{
  public:
    A* operator -> ()
    {
      if ( m_value < 0 )
        throw std::out_of_range("must be positive");
        
      return this;
    }
    int Get()
    {
      return m_value;
    }
  private:
    int m_value = 1;
};


int main()
{
    A a;
    
    int n1 = a->Get(); // check value
    int n2 = a.Get();  // direct access
    
    std::cout << n1 << ", " << n2 << std::endl;
    return 0;
}

http://ideone.com/vEDJoz

В частности, есть попытки Страуструпа и других здесь разрешить перегрузку оператора '.'. Если это будет сделано, то синтаксическая разница междц указателем и объектом полностью размоется.
И каждый день — без права на ошибку...
Re: Ссылки и указатели
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 28.06.19 15:57
Оценка:
Здравствуйте, x-code, Вы писали:

XC>В чем по-вашему преимущества и недостатки обоих подходов? Что лучше — явность (однозначно виден способ передачи объекта в функцию, способ обращения к нему и т.д.) или унификация доступа (везде точка, никаких разыменований)? Какой подход вам больше нравится? Правильно ли то, что в С++ сосуществуют оба способа, почему так сложилось, дает ли это какие-то преимущества и создает ли это какие-либо проблемы?


Различение способов доступа создает на ровном месте трудности для написания обобщенного/генерик кода. Когда доступ везде через точку, то такую функцию
auto sumAB(T)(T obj) {
    return obj.a + obj.b;
}

я могу использовать с любым классом и структурой, где есть подходящие поля a и b.
struct S {
    int a, b;
}

class C {
    double a, b, c;

    this() { a = 1; b = 2; c = 3; }
}

void main() {
    auto s = S(3,4);
    auto c = new C();
    sumAB(s).writeln;
    sumAB(c).writeln;
}


Или даже без генериков, просто если в каком-то коде я решу заменить класс структурой или наоборот, модификаций кода потребуется намного меньше, чем если б нужно было еще точки на стрелки менять. Как обычно, в С++ было неправильно, в D сделали правильно.
Re: Ссылки и указатели
От: wamaco  
Дата: 28.06.19 20:04
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Существует два синтаксических подхода к доступу к объектам, созданным динамически (в куче): через ссылки и через указатели. Обращение через ссылку неотличимо от непосредственного обрашения к объекту, обращение через указатель явно отличается (присутствует явное разыменование).


XC>В C# и Java используются ссылки, при этом введено соглашение что все объекты классов передаются по ссылке, а структуры и переменные примитивных типов — по значению. Там невозможно создать класс не стеке.


XC>В C, Go, Rust используются явные указатели и явное размыенование. То есть синтаксис косвенного обращения — через указатель — всегда отличается от синтаксиса прямого обращения к стековому или глобальному объекту. В С++ сосуществуют и указатели и ссылки, причем поведение ссылок отличается от такового в C#.


XC>В чем по-вашему преимущества и недостатки обоих подходов? Что лучше — явность (однозначно виден способ передачи объекта в функцию, способ обращения к нему и т.д.) или унификация доступа (везде точка, никаких разыменований)? Какой подход вам больше нравится? Правильно ли то, что в С++ сосуществуют оба способа, почему так сложилось, дает ли это какие-то преимущества и создает ли это какие-либо проблемы?


мне нравится, как сделано в Pascal
Re[2]: Ссылки и указатели
От: pagid Россия  
Дата: 02.07.19 05:50
Оценка:
Здравствуйте, wamaco, Вы писали:

W>мне нравится, как сделано в Pascal

В виртовском Паскале, в Object Pasccal из Turbo/Borland Pascal или в Паскале из Delphi? Если мне не изменяет мой склероз, там как раз это сделано по разному.
Re[2]: Ссылки и указатели
От: IID Россия  
Дата: 03.07.19 09:46
Оценка:
Здравствуйте, B0FEE664, Вы писали:


BFE>Во-первых, С++ может использоваться для прямого доступа к памяти по физическому адресу. Это обеспечивается с помощью указателей


Поправлю.
В общем случае физический адрес скрыт внутри MMU и недоступен приложению. Прикладной софт оперирует исключительно виртуальными адресами.
Устройства без MMU это, в основном, простейшие микроконтроллеры + Bare Metal.

BFE>Во-вторых, в С++ есть арифметика на указателях, которая непосредственно связана с предыдущем пунктом.

BFE>В-третьих, идеологически голые указатели в С++ не нужны, кроме как для доступа по физическим адресам.

Арифметика указателей удобна для работы с массивами объектов. Даже без привязки к смыслу значения указателя, пусть он хоть в попугаях будет.
kalsarikännit
Re[3]: Ссылки и указатели
От: B0FEE664  
Дата: 03.07.19 12:10
Оценка:
Здравствуйте, IID, Вы писали:

BFE>>Во-первых, С++ может использоваться для прямого доступа к памяти по физическому адресу. Это обеспечивается с помощью указателей


IID>Поправлю.

IID>В общем случае физический адрес скрыт внутри MMU и недоступен приложению.
Зависит от того, что называть общим случаем.

IID>Прикладной софт оперирует исключительно виртуальными адресами.

"Прикладной" софт бывает разный.

IID>Устройства без MMU это, в основном, простейшие микроконтроллеры + Bare Metal.

Как раз из этого уровня "пришли" указатели в C, а потом и в С++.

IID>Арифметика указателей удобна для работы с массивами объектов. Даже без привязки к смыслу значения указателя, пусть он хоть в попугаях будет.

Для двумерных (и большей размерности) массивов арифметика указателей настолько неудобна, что практически никогда не используется с указателями.
В современном С++ арифметика указателей используется с особыми объектами, называемыми итераторами, которые совсем не указатели на объекты, а указатели на положение в структуре данных. Поэтому итераторы имеют больший уровень абстракции, чем уровень абстракции указателей. Например, итератор может перебирать байты всех файлов лежащих в каталоге с помощью функции std::find. Такой итератор, конечно, можно называть указателем, вот только от обычного указателя итератор отличается весьма.
И каждый день — без права на ошибку...
Re: Ссылки и указатели
От: кт  
Дата: 03.07.19 12:31
Оценка:
Здравствуйте, x-code, Вы писали:


XC>почему так сложилось, дает ли это какие-то преимущества и создает ли это какие-либо проблемы?


Сложилось так еще в PL/1 в 1967 году.
Так как можно было задать указатель в описании, но при любом обращении «перевесить» указатель явно на любой другой:
declare 
a (100) float based(p1),
(p1,p2) ptr;
allocate a;
a=0;      // ссылка
p2=p1;
p2->a=0;  // точно такой же эффект

никаких особых проблем это не создавало, наоборот «в теле такая приятная гибкость образовалась…» (с) м/ф «Падал прошлогодний снег»
Re: Ссылки и указатели
От: _hum_ Беларусь  
Дата: 31.07.19 11:53
Оценка:
Здравствуйте, x-code, Вы писали:

XC> Правильно ли то, что в С++ сосуществуют оба способа, почему так сложилось, дает ли это какие-то преимущества и создает ли это какие-либо проблемы?


В С++ ссылки и указатели имеют несколько разную семантику для присваивания: ptr1 = ptr2 — присваивание "одного указателя другому", ref_1 = ref_2 — присваивание "значения, на которое ссылается вторая ссылка, значению, на которое ссылается первая".
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.