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

Для любителей обсудить что круче Linux или Win32, Java или C#.

Модератор: Duncon

Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

08 ноя 2004, 13:53

DeeJayC прав, COut надо передавать по ссылке.
Может оказаться так что одна или несколько ссылок на StringBuffer будут неучтены, поскольку конструктор CString не отработает.
Тогда StringBuffer будет удален раньше времени и закончится это Protection fault'ом.
Программист всегда предпочитает пользоваться теми средствами, которыми владеет лучше
Это да. Нормальными средствами тяжело владеть.
Любое более-менее сложное решение подразумевает состыковку. Это нормальная часть работы программиста, работающего в команде.
Сейчас заставляю работать один модуль, написанный каким-то Шакилой, который в качестве параметра берет не List, а Vector, вместо потока - имя файла итп. Требует пермишены на запись для своих конфигов, которые он только читает и не модифицирует.
Какой бы это ужас был, если бы это было не на Яве, а на С++ :()
Насчет мудаков и исключений - не вижу корреляции.
В C++ нету исключений. Использовать то, чего нет - это мудачество.
Нету ключевого слова finally, нету уборки мусора.
Я не говорю, что нужно делать уборку мусора обязачельно - достаточно по дефолту делать,
скажем, подсчет ссылок, и включить в библиотеку хедер <gc.h>,
который можно было бы использовать опционально.
auto_ptr - это вообще чудо. Он меняет свое содержимое при присваивании.
Такой ужас надо еще постараться придумать.
Откуда пошло слово мудак:
Обычно монголы кастрировали русских мужчин.
Но для некоторых это была большая трагедия, и монголам было их жалко.
Поэтому им усекали спермоносные каналы, и количество мужских гормонов не менялось.
Трахаться они могли, могли эякулировать чистым предстательным соком,но детей они
иметь не могли.
Отсюда пошло слово "мудак" - то есть вроде бы при мудях, а вроде бы и нет.
2B OR NOT(2B) = FF
Eugie
Сообщения: 707
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

09 ноя 2004, 17:32

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

PS. Спасибо, что просветил по вопросу этимологии :) М***ки, в сущности, вызывают сочувствие как невинные жертвы татаро-монгольского ига :) ))
Eugie
Сообщения: 707
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

10 ноя 2004, 17:04

Если кто-то ссылается на объект a, b или c через ссылку, тогда получается что
На строку Hello world ссылаются четыре или больше раз, а счетчик ссылок равен 3.
Вот тут ты не прав. Внутренний счетчик ссылок на строку не инкрементируется при передаче параметра по ссылке. Дело в том, что он может модифицироваться только при вызове конструктора копирования или при присваивании, а при передаче параметра по ссылке ни того, ни другого не происходит.
Аватара пользователя
AiK
Сообщения: 2271
Зарегистрирован: 13 фев 2004, 18:14
Откуда: СПб
Контактная информация:

10 ноя 2004, 17:19

Absurd, ты зачем шифруешься? :)
Даже самый дурацкий замысел можно воплотить мастерски
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

12 ноя 2004, 13:48

Внутренний счетчик ссылок на строку не инкрементируется при передаче параметра по ссылке.
Я это и имел в виду. Передали кому-то CString и не учли новую ссылку. В многопоточной среде может случиться преждевременное обнуление счетчика.
Absurd, ты зачем шифруешься?
Глюк форума
2B OR NOT(2B) = FF
Eugie
Сообщения: 707
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

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
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

17 ноя 2004, 20:13

При передаче куда-то ссылки на объект мы и не должны увеличивать счетчик референций, поскольку он предназначен для учета копий данного CString-объекта, а не С++-ссылок на него.
Какая разница? Все равно это нарушение политики, которую предстравляет смарт-указатель. В С++ есть соглашение (contract), что смарт - указатели должны пользоваться конструктором копирования и operator=() для отслеживания жизни указуемого объекта.
Если мы пользуем ссылку на смарт - указатель, то мы обходим его политику.
2B OR NOT(2B) = FF
Eugie
Сообщения: 707
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

18 ноя 2004, 17:49

CString - не смарт-указатель, хотя тоже умеет считать ссылки.
Absurd, приведи мне плиз конкретный пример кода, где передача CString в функцию по ссылке небезопасна. Иначе спорить можно еще долго, а время - деньги :)
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

22 ноя 2004, 13:10

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