Про ссылки и указатели (продолжение)

Ответить

Код подтверждения
Введите код в точности так, как вы его видите. Регистр символов не имеет значения.

BBCode ВКЛЮЧЁН
[img] ВКЛЮЧЁН
[flash] ОТКЛЮЧЕН
[url] ВКЛЮЧЁН
Смайлики ОТКЛЮЧЕНЫ

Обзор темы
   

Развернуть Обзор темы: Про ссылки и указатели (продолжение)

Eugie » 22 ноя 2004, 13:27

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

Absurd » 22 ноя 2004, 13:10

Absurd, приведи мне плиз конкретный пример кода, где передача CString в функцию по ссылке небезопасна
Указатель - это наиболее общий способ передачи ссылки на объект. Ссылки вторичны и служат инструментом для написания базовых примитивов в программе.
Значит, надо пользоваться указателями для соблюдения порядка в API.

Eugie » 18 ноя 2004, 17:49

CString - не смарт-указатель, хотя тоже умеет считать ссылки.
Absurd, приведи мне плиз конкретный пример кода, где передача CString в функцию по ссылке небезопасна. Иначе спорить можно еще долго, а время - деньги :)

Absurd » 17 ноя 2004, 20:13

При передаче куда-то ссылки на объект мы и не должны увеличивать счетчик референций, поскольку он предназначен для учета копий данного CString-объекта, а не С++-ссылок на него.
Какая разница? Все равно это нарушение политики, которую предстравляет смарт-указатель. В С++ есть соглашение (contract), что смарт - указатели должны пользоваться конструктором копирования и operator=() для отслеживания жизни указуемого объекта.
Если мы пользуем ссылку на смарт - указатель, то мы обходим его политику.

Eugie » 15 ноя 2004, 12:12

Я это и имел в виду. Передали кому-то CString и не учли новую ссылку. В многопоточной среде может случиться преждевременное обнуление счетчика.
Absurd, ты не мешай в одну кучу внутренние ссылки класса CString (назовем их для отличия референциями) и ссылки в смысле С++ (далее С++-ссылки). При передаче куда-то ссылки на объект мы и не должны увеличивать счетчик референций, поскольку он предназначен для учета копий данного CString-объекта, а не С++-ссылок на него. А копию объекта мы в этом случае не создаем. Логика подсчета референций CString (ты сам ее описал) не конфликтует с возможностью объявить произвольное число С++-ссылок на CString. С++-ссылка сама не является объектом и не может пережить связанный с ней объект по определению, т.к. 1) должна быть обязательно инициализирована; 2) инициализирующий объект не может иметь область видимости меньшую, чем связанная с ним ссылка. Т.е. защита от дурака здесь реализована средствами самого языка.

В случае многопоточности ситуация сложнее. С одной стороны, - ты, наверное, знаешь - модификация референций в CString потокобезопасна. С другой - можно исхитриться и передать в поток ссылку на временный объект, который к моменту обращения к нему из потока будет разрушен. Но, 1) это не так просто сделать, и 2) это не есть специфика класса CString. Проблема будет в случае любого типа данных (см.пример), просто такое действие будет явно деструктивным. Любую защиту ведь можно поломать, было бы желание :)

Пример намеренного нарушения правил работы с ссылками в многопоточной среде:

Код: Выделить всё

class A {
    int& m_r;
public:
    A(int& r): m_r(r) {}
    int GetByRef() { return m_r; }
};

unsigned long thrd_hdl;
unsigned thrd_addr;

unsigned __stdcall thread_routine(void *p)
{
    A* pa = reinterpret_cast<A*>(p);
    cout << pa->GetByRef() << endl;
    return 0;
}

void f()
{
   // Передаем в создаваемый поток ссылку на временную переменную типа int 
   // (через указатель на статичесий объект, т.к.напрямую нельзя). К моменту
   // вызова thread_routine ссылка становится инвалидной.
   // А если объявить static int n - все будет OK.
   int n = 1;
   static A a(n);

   thrd_hdl = _beginthreadex(
       NULL, 
       0, 
       thread_routine, 
       (void *)&a, 
       0, 
       &thrd_addr);
}

void main()
{
    f();
    Sleep(1000L);
}
PS. IMHO, надо бы вернуть топик в раздел C/C++ - вещи-то обсуждаем весьма серьезные. За вычетом филологических вопросов, конечно :)

Absurd » 12 ноя 2004, 13:48

Внутренний счетчик ссылок на строку не инкрементируется при передаче параметра по ссылке.
Я это и имел в виду. Передали кому-то CString и не учли новую ссылку. В многопоточной среде может случиться преждевременное обнуление счетчика.
Absurd, ты зачем шифруешься?
Глюк форума

AiK » 10 ноя 2004, 17:19

Absurd, ты зачем шифруешься? :)

Eugie » 10 ноя 2004, 17:04

Если кто-то ссылается на объект a, b или c через ссылку, тогда получается что
На строку Hello world ссылаются четыре или больше раз, а счетчик ссылок равен 3.
Вот тут ты не прав. Внутренний счетчик ссылок на строку не инкрементируется при передаче параметра по ссылке. Дело в том, что он может модифицироваться только при вызове конструктора копирования или при присваивании, а при передаче параметра по ссылке ни того, ни другого не происходит.

Eugie » 09 ноя 2004, 17:32

Может оказаться так что одна или несколько ссылок на StringBuffer будут неучтены, поскольку конструктор CString не отработает.
Тогда StringBuffer будет удален раньше времени и закончится это Protection fault'ом.
Какие ссылки, где учтены? В огороде бузина... ;) Absurd, уверяю тебя: передача параметра по ссылке вполне безопасна и по сути эквивалентна передаче по указателю. Если возражаешь, плиз приведи конкретный пример, а не общие слова.
В C++ нету исключений. Использовать то, чего нет - это мудачество.
В C++ есть исключения (см. throw, try, catch). Другое дело, что C++ модель exception handling низкоуровневая - все надо делать самому. Да, это неудобно, и, главное, трудоемко. Конечно, приятнее пользоваться развитой иерархией исключений какой-нить среды типа .NET
Нету ключевого слова finally, нету уборки мусора.
C++ такой язык - предоставляет минимум готовых решений, но при этом позволяет реализовать практически все самому. Согласен, что с finally и GC удобнее, особенно когда привык. К хорошему вообще быстро привыкаешь :)

PS. Спасибо, что просветил по вопросу этимологии :) М***ки, в сущности, вызывают сочувствие как невинные жертвы татаро-монгольского ига :) ))

Вернуться к началу