Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 23, средняя оценка - 4.65
HighPredator
5544 / 1857 / 346
Регистрация: 10.12.2010
Сообщений: 5,479
Записей в блоге: 2
#1

Coding style или нет - C++

09.02.2012, 19:56. Просмотров 3096. Ответов 60
Метки нет (Все метки)

Услышал сегодня от коллеги такую интересную вещь: есть блоки кода ограниченные командными скобками {}. Так вот, рекомендуется переменные, используемые в блоках и только в них, объявлять в таких блоках. Я например, как правило объявляю переменные в начале подпрограмм. Привычка. Вопрос такой: это чисто coding style рекомендация или есть какое-то практическое значение подобного действия?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.02.2012, 19:56
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Coding style или нет (C++):

Ошибка с массивами, хотя формально её нет (похожи ли массивы или нет?) - C++
Всем доброго времени суток!) В общем имею такую великолепную чтуку, она должна говорить мне, похожи ли массивы или нет, массив должен...

Вывести на экран слова, в которых все символы повторяющиеся, или сообщение «Нет», если требуемых слов нет - C++
Дана последовательность символов, состоящая из слов. Вывести на экран слова, в которых все символы повторяющиеся, или сообщение «Нет», если...

Как разбить код на 2 функции: Coding и Decoding? - C++
#include <iostream> #include <vector> #include <map> #include <list> #include <fstream> using namespace std; ...

Где можго почитать о Coding Convention для C++ на русскос языке? - C++
Я не смог нагуглить.

Как найти текст в файле и возвратить 0 или 1 в зависимости от того,найдено или нет? - C++
bool fnd(char* fn,string stf) { string s; ifstream ifs(fn); while (!ifs.eof()) { getline(ifs,s); ...

Вывести True или False в зависимости от того, имеют три заданных целых числа одинаковую четность или нет - C++
Всем привет! Помогите, пожалуйста в решении задачи. Знаю, что задачи более,или менее лёгкие,но я в c++ почти ничего не смыслю, а лабы...

60
silent_1991
Эксперт С++
4987 / 3044 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
10.02.2012, 14:34 #46
AzaKendler, никогда не обнулял указатель в деструкторе. Потому что не для того деструктор предназначен, чтобы когда нам заблагорассудится вызывался. Он должен вызываться для одного объекта один раз, при уничтожении, и точка. Это как с const_cast. Он вроде как есть, и его даже вроде как можно использовать, но если из-за него программа свалится в рантайме, то программист сам дурак.
Ну и плюс к тому, в своих классах можно обо всём позаботиться (напихать ключей, которые будут говорить, закрыт ли файл, разорвано ли соединение, очищена ли память, и проверять всё это в деструкторе), но проблема в том, что мы чаще используем чужой код, а не собственный. И при этом надо знать, что деструктор не предназначен для вызова вручную, и что если такой вызов будет иметь и место и затем будет иметь место падение в рантайме, то программист снова сам дурак.
0
Bers
Заблокирован
10.02.2012, 14:36 #47
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int GetLenth(int x1, int x2, int x3) 
{ 
    std::string str; str +=x1; str +=x2; str +=x3; 
    return str.size(); 
}
 
void func1 (int x1, int x2, int x3)
{
  int len = GetLenth(x1,x2,x3);
 
  // Здесь str нам больше не нужен. 
 
  for (i = 0; i < 1000000; i++)
    func2 (len);
}
Цитата Сообщение от Evg Посмотреть сообщение
Могут быть промежуточные значения
Ну вот, по поводу промежуточных значений...

Иногда, исключительно для читабельности, есть смысл завести промежуточный объект.
Но это переменные типа int какие нибудь...

Если же в качестве такого промежуточного объекта просится очень тяжелый объект - явно что то не в порядке в самой архитектуре.

Пример того, чего быть не должно:

MyClass a,b; //оч тяжелые объекты
...
MyClass c = a; a=b; b=c;

Пример того, что должно быть:
a.Swap(b); //перенацелятся лишь парочка указателей. Никакого копирования.

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


Цитата Сообщение от Evg Посмотреть сообщение
И в итоге из-за принципиальных соображений один нормально читаемый код в виде одной нормально читаемой функции превратится в десяток функций, в которых ориентироваться будет намного сложнее.
Этого не может быть. Есть только два варианта:
1. Весь код представляет собой монолитную размазню.
2. Код разбит на функции.

И если вспомогательных функций получился десяток другой, значит ваш "нормально читаемый код" просто хардкорно забил их текст внутри себя - монолитная чача.

Можно написать все в теле одной мега-раздутой функции. Можно разбить на десяток мелких.
Но само по себе "количество" кода либо не изменится, либо уменьшится, но только в случае разбиения на функции.
0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
10.02.2012, 14:36 #48
silent_1991, немного смысл утерян диалога. я выше в посте пометил почему началась эта тема.
конечно деструктор не нужно дергать дела без дела, а нужно только при необходимости/
А обнулять указатели надо по любому. поскольку в с++ delete нулевого указателя - это не ошибка, просто ничего не делается
а вот не обнуленного но уже ссылающегося на очищенную память - краш
0
Vourhey
Почетный модератор
6486 / 2260 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
10.02.2012, 14:45 #49
Evg, Bers прав... Если функция настолько велика, что вынуждает объявлять переменные в ее середине (без явных на то оснований), то это уже "говнокод". От величины и сложности проекта не зависящий.
Цитата Сообщение от Evg Посмотреть сообщение
один нормально читаемый код в виде одной нормально читаемой функции првреатится в десяток функций
Лучше 10 вызовов функций с говорящими именами, чем простыня на 100 строк в одной функции, из которых 40 на комментарии.
Цитата Сообщение от Evg Посмотреть сообщение
то на время работы цикла память, отжираемая
* // экземпляром str, будет необоснованно болтаться как использованная
Это никак не скажется на работе программы. (если только в следующих вызовах не соберемся стек переполнить, что получится сделать немного быстрее)
0
Evg
Эксперт CАвтор FAQ
18248 / 6373 / 438
Регистрация: 30.03.2009
Сообщений: 17,643
Записей в блоге: 28
10.02.2012, 14:52 #50
Цитата Сообщение от AzaKendler Посмотреть сообщение
но ты ведь вел речь об экономии памяти в стринге
string я использовал как пример экземпляра класса для наглядности. На его месте может быть любой самодельный класс, активно потребляющий память и работающий с файлами

Bers, вот тебе фрагмент отладчика gdb: файл infrun.c. См. функцию handle_inferior_event. Это одна большая логическая последоваттельность действий, которая потеряет всякую логику, будучи искусственно разбитой на маленькие запчасти

Добавлено через 1 минуту
Цитата Сообщение от Vourhey Посмотреть сообщение
Это никак не скажется на работе программы. (если только в следующих вызовах не соберемся стек переполнить, что получится сделать немного быстрее)
Я уже говорил, что string - условность. Это может быть экземпляр произсольного класса, который отожрал 10 мегабайт динамической памяти и которая освободится только при удалении объекта
0
Bers
Заблокирован
10.02.2012, 14:55 #51
Цитата Сообщение от AzaKendler Посмотреть сообщение
А обнулять указатели надо по любому. поскольку в с++ delete нулевого указателя - это не ошибка, просто ничего не делается
а вот не обнуленного но уже ссылающегося на очищенную память - краш
Вот я так и не определился с мыслью: ошибка это, или нет - удалять по нулевому указателю.

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

А если бы программка тихо промолчала - стало быть, и не узнал бы я, что у меня прокрался баг.

Из этих соображений, решил я ставить ассерт перед удалением. И ежели указатель уже ноль - стало быть в дебаге мне мой код об этом поведует. А в релизе сохранит работоспособность.
1
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
10.02.2012, 15:01 #52
Цитата Сообщение от Evg Посмотреть сообщение
который отожрал 10 мегабайт динамической памяти и которая освободится только при удалении объекта
если это самописный класс, то уже на совести того кто его писал предусмотреть аналог clear() и возможность очистки ДО удаления при выходе из области видимости.
Это уже более философский вопрос, касающийся того "а что за человек писал код".

Добавлено через 3 минуты
Bers, ну если ты предпочитаешь так проверяться то да. ты практикующий постоянно судя по всему. к тебе можно прислушаться.
но при тестах ты можешь и не найти ту ошибку которая приводит к крашу и не обнаружить какие то петли и повторные вызовы. это может произойти у клиента. ну а если будет 0, то будет работать пока ты готовишь апдейты или проводишь доп тесты.
ну это такая фантазия

я же лишь черпаю информацию из книг и форума. в книгах рекомендуют нулить.

Добавлено через 1 минуту
Цитата Сообщение от Bers Посмотреть сообщение
И ежели указатель уже ноль
все таки нулишь?
0
Evg
Эксперт CАвтор FAQ
18248 / 6373 / 438
Регистрация: 30.03.2009
Сообщений: 17,643
Записей в блоге: 28
10.02.2012, 15:04 #53
Цитата Сообщение от AzaKendler Посмотреть сообщение
все таки нулишь?
Он нулит его только для того, чтобы поймать ситуацию повторного вызова деструктора. И это правильный способ.
1
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
10.02.2012, 15:05 #54
Цитата Сообщение от Bers Посмотреть сообщение
Вот я так и не определился с мыслью: ошибка это, или нет - удалять по нулевому указателю
думаю не ошибка. указатель может быть установлен в 0 в конструкторе и ждать некой функции Init();
если инит не вызван то указатель так и будет 0, и в деструкторе будет delete 0. если инит отработает то будет что то удалено из
памяти в деструкторе как и задумывалось
0
silent_1991
Эксперт С++
4987 / 3044 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
10.02.2012, 15:05 #55
AzaKendler, clear в том же стринге память не очищает. В векторе, например, тоже. Т.е. ни стринг, ни вектор вообще никогда не уменьшают размера. Пример:
http://liveworkspace.org/code/4df806d1fb3c3a6c2a11d68864746f5c
Напомню, что capacity возвращает количество элементов, которое контейнер может вместить без очередного выделения памяти.
0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
10.02.2012, 15:10 #56
silent_1991, тогда resize(0). за клиар сорри. спасибо за уточнения уж если писать то точно.
имел ввиду принцип очистки до удаления. напутал функцию
0
Bers
Заблокирован
10.02.2012, 15:11 #57
Цитата Сообщение от AzaKendler Посмотреть сообщение
все таки нулишь?
Есть два режима: дебаг, и релиз.
Дебаг - это версия для отладки. Релиз - это версия для клиента.

В дебаге ассерты срабатывают. В релизе, код проверок будит выброшен препроцессором и не будет скомпилирован.

Перед удалением у меня стоит ассерт, который сработает, если указатель нулевой.
А после удаления, соответственно, зануляет указатель.

Таким образом, в дебаге у меня будет проверка на попытку двойного удаления.
А в релизе никаких проверок вообще уже не существует. Но так как указатели зануляются, то попытка двойного удаления вреда не нанесет.

Поэтому, в дебаге я сразу узнаю, если будет такой косяк. А в релизе - ну.. есть надежда, что приложение выживет.

Тут есть свои нюансы: например, если объект в принципе имеет право "не выделять динамическую память". Допустим, при создании, он ещё пустой, и его указатель нулевой. То.. он имеет право делетить нулевой указатель.
А если объект при создании автоматически выделяет память - тогда не имеет.
1
silent_1991
Эксперт С++
4987 / 3044 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
10.02.2012, 15:17 #58
AzaKendler, clear и есть resize(0). Невозможно уменьшить размер выделенной в строке памяти извне. Даже reserve(0) не поможет.

Добавлено через 1 минуту
Вру.
Можно так:
C++
1
2
str.resize(0);
str.reserve(0);
Добавлено через 1 минуту
Но это только со строкой. Вектор совершенно отказывается "расти вниз".
0
Bers
Заблокирован
10.02.2012, 15:18 #59
silent_1991

C++
1
void ClearStr(std::string& obj) {   std::string tmp; tmp.swap(obj); }
0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
10.02.2012, 15:19 #60
silent_1991, чтож остается только swap с пустым классом
0
10.02.2012, 15:19
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.02.2012, 15:19
Привет! Вот еще темы с ответами:

Опечатка или нет? - C++
class my_class { public: my_class() { a = b = 0; } my_class(constint...

симафор или нет? - C++
ПРивет всем! написал программу для следующего задания с использованием симафора: Написать программу, создающую два потока. Оба...

C++11 в production, да или нет? - C++
Всем привет. Выбил все-таки разрешение юзать С++11 на работе, по мелочи, лямбды вместо предикатов, range-based-for, auto. Сегодня наш тех....

Палиндром или нет? - C++
Определить, является ли заданное натуральное число палиндромом, т.е. таким, десятичная запись которого читается одинаково слева направо и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru