Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как не надо писать код 
:(
    Опции темы
Jeka178RUS
Дата 2.9.2013, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 85
Регистрация: 3.9.2012

Репутация: нет
Всего: нет



Чем же рекурсия так плоха? Накладные расходы на вызов функции, как мне кажется, не существенны (не берем в расчет критические отрасли, как контроллеры и пр.). Разве что отладка не удобна
PM MAIL   Вверх
bsa
Дата 2.9.2013, 15:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(ТарасАтавин @  29.8.2013,  20:07 Найти цитируемый пост)
И поминавшийся здесь явный вызов конструктора. Конструктор и деструктор придуманы именно для того, чтоб вызываться автоматически, чтоб уж точно не забыть из вызвать и, наоборот, не забыть, что уже вызвал.
ну если ты не знаешь, зачем нужна возможность ручного вызова конструктора и деструктора, то это не значит, что никому это не нужно. Хинт: попробуй реализовать std::vector::reserve() со всеми побочными явлениями без использования прямых вызовов.
Цитата(ТарасАтавин @  30.8.2013,  05:58 Найти цитируемый пост)
Но рекурсия на пустом месте - это именно то, чего делать не надо. 
рекурсию на пустом месте делают только преподаватели. Сам программист редко когда делает рекурсию там, где и без нее все хорошо получается.
PM   Вверх
ТарасАтавин
Дата 3.9.2013, 05:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(bsa @  2.9.2013,  15:01 Найти цитируемый пост)
рекурсию на пустом месте делают только преподаватели.
Преподаватели этим занимаются при подаче нового материала по теме "рекурсия", чтоб показать, что это вообще такое. Но когда ею пестрят учебные поделухи, это нормально. В реальных же прогах рекурсия должна быть там и только там, где она вытекает или из задачи, или из представления данных. Да и то бывает, что вместо рекурсии надо обратиться к математику, который объяснит, что матрицу экономнее привести к треугольному виду, а потом перемножить главную диагональ, чем считать определитель рекурсивным алгоритмом. На КМК есть целый отдел любителей рекурсии.

Добавлено @ 05:53
Цитата(Jeka178RUS @  2.9.2013,  13:00 Найти цитируемый пост)
Чем же рекурсия так плоха? Накладные расходы на вызов функции, как мне кажется, не существенны (не берем в расчет критические отрасли, как контроллеры и пр.). Разве что отладка не удобна 
Один вызов? Или много? Кроме того, они зависят от параметров, при всего лишь одном тяжёлом параметре типа двумерный массив памяти при рекурсивном вычислении определителя хватило всего на 1237 вызовов на 6-ти уровнях. Да и не в расходах на вызов обычно дело. В случае, например, факториала рекурсия соответствует двум циклам вызовов и возвратов вместо одного.

Добавлено @ 05:56
Цитата(bsa @  2.9.2013,  15:01 Найти цитируемый пост)
ну если ты не знаешь, зачем нужна возможность ручного вызова конструктора и деструктора, то это не значит, что никому это не нужно. Хинт: попробуй реализовать std::vector::reserve() со всеми побочными явлениями без использования прямых вызовов.
 Явный вызов конструктора отлично заменяется присваиванием вспомогательного локального объекта, в котором напутать уже нельзя. А вот к чему приведёт двойной вызов конструктора для одного и того же динамического объёкта по указателю без тестов не разберёт и сам Страуструп.

Это сообщение отредактировал(а) ТарасАтавин - 3.9.2013, 05:59


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
bsa
Дата 3.9.2013, 10:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(ТарасАтавин @  3.9.2013,  06:45 Найти цитируемый пост)
 Явный вызов конструктора отлично заменяется присваиванием вспомогательного локального объекта, в котором напутать уже нельзя.
ну ну. А если еще раз подумать? Хинт: как поведет себя оператор присваивания с неинициализированным объектом?

Цитата(ТарасАтавин @  3.9.2013,  06:45 Найти цитируемый пост)
А вот к чему приведёт двойной вызов конструктора для одного и того же динамического объёкта по указателю без тестов не разберёт и сам Страуструп.
У меня такой вопрос, а нахрена вызывать конструктор два раза? Ты вообще знаешь, как он вызывается? Или ты путаешь вызов конструктора с созданием объекта?

и вообще. Языки С/С++ очень гибкие. Поэтому на них очень легко получается совершать ошибки. Хочешь не совершать? Пиши на Ada.
PM   Вверх
Jeka178RUS
Дата 3.9.2013, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 85
Регистрация: 3.9.2012

Репутация: нет
Всего: нет



Замечательный пример "как не надо делать" я нашел в недрах Ericsson Labs: в одном файле утилиты для сжатия текстур  16 000 строк кода на С. Насколько нужно быть упоротым человеком чтобы так кодить?

Это сообщение отредактировал(а) Jeka178RUS - 3.9.2013, 12:38
PM MAIL   Вверх
ТарасАтавин
Дата 5.9.2013, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(bsa @  3.9.2013,  10:30 Найти цитируемый пост)
У меня такой вопрос, а нахрена вызывать конструктор два раза?
Затем, что забыл, что один раз уже вызвал.

Добавлено @ 11:26
Цитата(bsa @  3.9.2013,  10:30 Найти цитируемый пост)
 Хинт: как поведет себя оператор присваивания с неинициализированным объектом?
Думаешь я не реаллокил массивы объектов? Нормально он себя поведёт, непроиниченный объект просто содержит мусор. Ну и что, если его всё равно надо затереть нормальными данными?

Это сообщение отредактировал(а) ТарасАтавин - 5.9.2013, 11:27


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
bsa
Дата 5.9.2013, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(ТарасАтавин @  5.9.2013,  12:24 Найти цитируемый пост)
Думаешь я не реаллокил массивы объектов? Нормально он себя поведёт, непроиниченный объект просто содержит мусор. Ну и что, если его всё равно надо затереть нормальными данными?
Садись. Кол тебе! Бегом читать книжки по С++ для начинающих.

Цитата(ТарасАтавин @  5.9.2013,  12:24 Найти цитируемый пост)
Затем, что забыл, что один раз уже вызвал.
Кстати, а ты вообще знаешь, как вызвать конструктор класса? А деструктор? И часто ты их вызываешь вручную?
Кстати, следуя этой логике не нужны и new/delete, так как можно два раза выделить память.
PM   Вверх
ТарасАтавин
Дата 5.9.2013, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(bsa @  5.9.2013,  12:30 Найти цитируемый пост)
Садись. Кол тебе! Бегом читать книжки по С++ для начинающих.
Сам читай. У меня 13 лет практического опыта.

Добавлено @ 14:11
Цитата(bsa @  5.9.2013,  12:30 Найти цитируемый пост)
Кстати, а ты вообще знаешь, как вызвать конструктор класса? А деструктор? И часто ты их вызываешь вручную?
Ни когда. 
Цитата(bsa @  5.9.2013,  12:30 Найти цитируемый пост)
Кстати, следуя этой логике не нужны и new/delete, так как можно два раза выделить память. 
А как тогда вообще хоть что то писать? Резервировать массивы, как во времена лорда Клайва Синклера? К тому же new/delete мудрено забыть, так как они  естественно вытекают из динамического создания/удаления. А конструкторы/деструкторы придуманы именно для того, чтоб вызываться неявно. Иначе юзай вместо них методы Create/Free, больше ни в чём конструкторам/деструкторам не уступающие.

Это сообщение отредактировал(а) ТарасАтавин - 5.9.2013, 14:16


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
bsa
Дата 5.9.2013, 15:26 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(ТарасАтавин @  5.9.2013,  15:09 Найти цитируемый пост)
У меня 13 лет практического опыта.
Опыт опыту рознь. Некоторые новички и то больше знают и умеют.
Цитата(ТарасАтавин @  5.9.2013,  15:09 Найти цитируемый пост)
Ни когда. 
Ответ на вопрос о способах вызова конструктора и деструктора я так и не получил. Значит не знаешь. Тогда о чем вообще речь? Как ты можешь критиковать что-то, что ты вообще никогда не видел и уж тем более не задумывался о назначении.

Цитата(ТарасАтавин @  5.9.2013,  15:09 Найти цитируемый пост)
А как тогда вообще хоть что то писать?
Это к тебе вопрос, а не ко мне. Так как это ты выразил мысль, что явный вызов конструкторов и деструкторов не нужен, так как может привести к повторной инициализации.

Так как кто-то книжки читать не любит (видимо на основании 13-ти летного опыта), то справочно сообщаю, что явно вызвать конструктор класса можно только используя так называемый "размещающий new" (указанный пример кода показывает на сколько это нетривиальная операция, по которой даже нельзя сказать, что это вызов конструктора). А операция MyClass() не является вызовом конструктора в чистом виде - это фактически создание временного объекта связанное с вызовом указанного конструктора.
PM   Вверх
ТарасАтавин
Дата 5.9.2013, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(bsa @  5.9.2013,  15:26 Найти цитируемый пост)
Это к тебе вопрос, а не ко мне. Так как это ты выразил мысль, что явный вызов конструкторов и деструкторов не нужен, так как может привести к повторной инициализации.
Я имел ввиду только конструкторы/деструкторы, которым в такой ситуации здорово психологически мешает неявный вызов, о котором думать не надо. А new/delete применяются только явно и предназначены для указания момента создания/удаления. Если ты хочешь создать нечто в определённый момент, так неужели ж забудешь, когда именно и сколько раз? И совсем другое дело создание вообще той же сущности.

Добавлено через 3 минуты и 58 секунд
Цитата(bsa @  5.9.2013,  15:26 Найти цитируемый пост)
Так как кто-то книжки читать не любит (видимо на основании 13-ти летного опыта), то справочно сообщаю, что явно вызвать конструктор класса можно только используя так называемый "размещающий new" (указанный пример кода показывает на сколько это нетривиальная операция, по которой даже нельзя сказать, что это вызов конструктора). А операция MyClass() не является вызовом конструктора в чистом виде - это фактически создание временного объекта связанное с вызовом указанного конструктора. 
"Это не вызов конструктора, а создание объекта и для этого вызов конструктора"? Ты серьёзно? Одно от другого ваще то не отделимо: объекты создаются только конструкторами, а конструкторы всегда создают объекты. Читай книги.



--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
akizelokro
Дата 5.9.2013, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Тарас, цепляй ObjectiveC. На Западе многие его юзают, кстати. По крайней мере в заказах постоянно вижу.


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
ТарасАтавин
Дата 5.9.2013, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(bsa @  5.9.2013,  15:26 Найти цитируемый пост)
Опыт опыту рознь. Некоторые новички и то больше знают и умеют.
О присваивании непроиниченному объекту? Ну ну. Я это практически делал. И наблюдал под дебагером, что именно у меня получалось.

Добавлено через 1 минуту и 28 секунд
Цитата(akizelokro @  5.9.2013,  16:11 Найти цитируемый пост)
Тарас, цепляй ObjectiveC.
Си с классами вместо полноценного объектного языка? Сам цепляй эту полумеру.


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
bsa
Дата 5.9.2013, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(ТарасАтавин @  5.9.2013,  17:11 Найти цитируемый пост)
Си с классами вместо полноценного объектного языка? Сам цепляй эту полумеру
Ну почему же ты постоянно пытаешься спорить по вопросам, в которых ничего не понимаешь?
Цитата(ТарасАтавин @  5.9.2013,  17:05 Найти цитируемый пост)
"Это не вызов конструктора, а создание объекта и для этого вызов конструктора"? Ты серьёзно? Одно от другого ваще то не отделимо: объекты создаются только конструкторами, а конструкторы всегда создают объекты
Да. Отличимо. Конструктор - это по сути функция, которая используется для инициализации объекта. А создание временной переменной - это выделение памяти в стеке, вызов конструктора и планирование вызова деструктора (кстати, все это делается неявно). То что синтаксис похож на вызов конструктора не говорит ни о чем - просто для удобства. Два раза проинициализировать один и тот же объект таким образом невозможно.

Добавлено через 1 минуту и 5 секунд
Цитата(ТарасАтавин @  5.9.2013,  17:05 Найти цитируемый пост)
Я имел ввиду только конструкторы/деструкторы, которым в такой ситуации здорово психологически мешает неявный вызов, о котором думать не надо.
Че?

Добавлено через 8 минут и 34 секунды
Кстати, есть очень красивая реализация оператора присваивания с использованием создания временной переменной:
Код
MyClass& MyClass::operator=(const MyClass &other)
{
   MyClass(other).swap(*this);
/*
   Можно написать так:
   MyClass tmp(other);
   tmp.swap(*this);
   но вариант выше короче (генерируемый код одинаков)
*/
}

PM   Вверх
ТарасАтавин
Дата 7.9.2013, 08:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(bsa @  5.9.2013,  17:37 Найти цитируемый пост)
Да. Отличимо. Конструктор - это по сути функция, которая используется для инициализации объекта. А создание временной переменной - это выделение памяти в стеке, 
Временной переменной, или временного объекта? Создание автоматического/динамического объекта состоит из выделения памяти и вызова конструктора по адресу этой памяти. Пока конструктор не отработал, объект не создан, будь он хоть трижды временным.

Добавлено @ 08:08
Цитата(bsa @  5.9.2013,  17:37 Найти цитируемый пост)
Да. Отличимо. Конструктор - это по сути функция, которая используется для инициализации объекта. 
 Вот именно. Обычная функция, отличающаяся ровно двумя признаками:
1. Может вызываться не явно при входе в область видимости, в которой декларирован автоматический объект, при загрузке модуля, в котором декларирован статический объект и из оператора new.
2. Предназначена для начальной инициализации объекта,
За назначением остальных функций следит автор, в том числе их можно предназначить для той же цели, что и конструктор. И что же остаётся от конструктора, если его пытаются вызвать явно? Placement new же вызывает конструкторы не явно. Кстати, пустые конструкторы инициализацией не занимаются, их назначение - соблюдение формального правила о создании объектов только через конструктор. Но почему-то 
Код
class TVector {double x,y,z;};
TVector a;
TVector b;
b.x=2.0;
b.y=3.0;
b.z=4.68;
a=b;
 отлично компилится и исполняется, хотя конструктор класса TVector здесь пуст и объект a не инитится. Присваивание по указателю после malloc/realloc ни чем не отличается. Проверено.

Это сообщение отредактировал(а) ТарасАтавин - 7.9.2013, 19:21


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
bsa
Дата 9.9.2013, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(ТарасАтавин @  7.9.2013,  09:03 Найти цитируемый пост)
Временной переменной, или временного объекта?
Может написать отличия?
Цитата(ТарасАтавин @  7.9.2013,  09:03 Найти цитируемый пост)
Создание автоматического/динамического объекта состоит из выделения памяти и вызова конструктора по адресу этой памяти. Пока конструктор не отработал, объект не создан, будь он хоть трижды временным.
Я написал что-то противоречащее этому утверждению?
Цитата(ТарасАтавин @  7.9.2013,  09:03 Найти цитируемый пост)
Может вызываться не явно при входе в область видимости
Она вызывается не при входе в область видимости, а при инициализации переменной (объекта). Т.е. если переменная объявлена в конце блока, то конструктор она не вызовется сразу при входе.
Цитата(ТарасАтавин @  7.9.2013,  09:03 Найти цитируемый пост)
И что же остаётся от конструктора, если его пытаются вызвать явно?
Как ты вызываешь конструктор явно? Покажи пример кода!
Цитата(ТарасАтавин @  7.9.2013,  09:03 Найти цитируемый пост)
Placement new же вызывает конструкторы не явно.
Ты можешь сколько угодно тут разводить демагогию про явно и неявно, но placement new делает только одну операцию: вызов конструктора класса для инициализации объекта в указанной области памяти. И все! Поэтому я никогда бы не сказал, что он делает это неявно.
Цитата(ТарасАтавин @  7.9.2013,  09:03 Найти цитируемый пост)
Кстати, пустые конструкторы инициализацией не занимаются, их назначение - соблюдение формального правила о создании объектов только через конструктор.
И? Я где-то этому противоречил?
Цитата(ТарасАтавин @  7.9.2013,  09:03 Найти цитируемый пост)
отлично компилится и исполняется, хотя конструктор класса TVector здесь пуст и объект a не инитится.
И? Я где-то опровергал это?
Цитата(ТарасАтавин @  7.9.2013,  09:03 Найти цитируемый пост)
Присваивание по указателю после malloc/realloc ни чем не отличается. Проверено.
Проверь теперь этот код:
Код
std::string *p = (std::string*)malloc(sizeof(*p) * 5);
*p = "1234";
p = realloc(p, sizeof(*p) * 20);
*p = "3456";
И объясни (главное себе), почему он не работает. 

PM   Вверх
Google
  Дата 14.10.2019, 06:46 (ссылка)  





  Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1692 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.