Форум программистов, компьютерный форум, киберфорум
Священные войны
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.64/56: Рейтинг темы: голосов - 56, средняя оценка - 4.64
Эксперт С++
 Аватар для grizlik78
2383 / 1667 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
03.07.2011, 11:20
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от easybudda Посмотреть сообщение
Цитата Сообщение от Bers Посмотреть сообщение
это рекомендованный способ удаления элемента из мапы:
Простите, кем рекомендованный?
Некий Джефф Элждер в книге с оригинальным названием "С++" как-раз предупреждает об опасности подобных конструкций, обосновывая это тем, что компилятор, которым Вы компилируете программу, может действовать не так, как тот, что у Вас в голове, и сначала удалить объект, на который указывает pos, после чего сделать копию pos, увеличить её значение и результат снова присвоить pos. В результате увеличиваться будет уже не валидный итератор, и чем дело обернётся - загадка...
Обсуждаемый код есть в книге Н.Джосьютиса "C++. Стандартная библиотека". Там он, кстати, упрекает разработчиков библиотеки за то, что они практически вынуждают пользоваться столь сложными и непонятными конструкциями.
Однако касательно вызова
C++
1
coll.erase(pos++);
стандарт C++ кое-что всё-таки гарантирует (2003, п.5.2.2.8):
The order of evaluation of arguments is unspecified. All side effects of argument expression evaluations take effect before the function is entered. The order of evaluation of the postfix expression and the argument expression list is unspecified.
То есть обещается, что к моменту вызова функции итератор обретёт-таки своё новое значение, а функция будет работать со старой копией. Нельзя закладываться только на порядок вычисления аргументов и частей выражений.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
03.07.2011, 11:20
Ответы с готовыми решениями:

Что означает ptr в строке byte ptr[si],al
Что означает ptr в строке byte ptr,al Вот весь код, может понадобится Преобразование двоичного числа в шестнадцатеричную форму ...

Ошибка на стадии выполнения ptr = ptr;
class CObject { friend Parser; // много полей методов, все должны заполняться в парсере } class Parser { CObject * object_...

bad ptr
Здравствуйте! Пишу небольшую программу для работы с текстом. При substr'е куска строки вывелся не только нужный мне кусок, но и немного...

200
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,980
03.07.2011, 11:57
Цитата Сообщение от accept Посмотреть сообщение
ptr == NULL сразу ясно, что ptr - указатель, потому что в C NULL - (void *) 0 (нулевой адрес)
Аргумент, конечно, но не панацея от ошибок. Написали что-то вроде
C
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
 
char ptr; // Ну забыли звёздочку и перечитывали "не вкуривая".
 
int main(void){ 
    // примерно через 500 строк
    if ( ptr == NULL )
        printf("Null pointer.\n");
    else
        printf("Something else.\n");
    
    return 0;
}
Забили на строчку с предупреждением - программа-то скомпилировалась, а мы, напомню, не задумываемся. К тому же на 500+ строк подобного кода и предупреждений может быть гораздо больше. Программа при этом запускается и пишет "Null pointer". Сколько раз другой человек должен не задумываясь все её 500+ строк перечитать, чтобы догадаться, что ptr обычно сокращение от pointer, а оно как char объявлено?

Добавлено через 9 минут
Цитата Сообщение от grizlik78 Посмотреть сообщение
Обсуждаемый код есть в книге Н.Джосьютиса "C++. Стандартная библиотека". Там он, кстати, упрекает разработчиков библиотеки за то, что они практически вынуждают пользоваться столь сложными и непонятными конструкциями.
Цитата Сообщение от grizlik78 Посмотреть сообщение
стандарт C++ кое-что всё-таки гарантирует (2003, п.5.2.2.8):
Спасибо, конечно, буду знать теперь. Но пользоваться подобной конструкцией всё равно не стал бы. Сокращённая запись - это та, которой можно более длинную заменить. А когда приходится так делать - это уже фигня какая-то...
0
4866 / 3287 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
03.07.2011, 11:59
Цитата Сообщение от easybudda
C
1
// Ну забыли звёздочку и перечитывали "не вкуривая".
тогда пишем if (ptr == '\0')
неважно, как называется переменная
главное, что эта строка ясно сообщает, какой тип у ptr, в то время как !ptr сохраняет загадку
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,980
03.07.2011, 12:06
Цитата Сообщение от accept Посмотреть сообщение
тогда пишем if (ptr == '\0')
неважно, как называется переменная
Так оно по задумке и должно быть указателем, звёздочку именно забыли поставить. А вот с понятными названиями переменных и сам код понятнее становится. При чём относится это далеко не только к конструкциям вроде ! ptr... Нет?

accept, я же не спорю, что == NULL понятнее, я к тому что "понятный" код ещё не гарантия того, что он правильный.
0
Эксперт С++
 Аватар для grizlik78
2383 / 1667 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
03.07.2011, 12:10
Цитата Сообщение от easybudda Посмотреть сообщение
Сокращённая запись - это та, которой можно более длинную заменить. А когда приходится так делать - это уже фигня какая-то...
Дык она и заменяет более длинную
Только в соответствии с процитированным пунктом стандарта код
C++
1
2
3
4
5
6
7
8
for (pos = coll.begin(); pos != coll.end(); ) {
    if (pos->second == value) {
        coll.erase(pos++);
    }
    else {
        ++pos;
    }
}
заменяет такую, более громоздкую, конструкцию:
C++
1
2
3
4
5
6
7
8
9
10
for (pos = coll.begin(); pos != coll.end(); ) {
    if (pos->second == value) {
        SomeMap::iterator oldpos = pos;
        ++pos;
        coll.erase(oldpos);
    }
    else {
        ++pos;
    }
}
а не вызов функции с последующим инкрементом.
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
03.07.2011, 12:15
все равно способ подозрительный, всегда использовал нечто вроде

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <map>
#include <iostream>
#include <algorithm>
#include <string>
 
template<class Key, class Val> struct _equal
{
  _equal( const Val& val ) : m_val( val ) {}
  bool operator()( const std::pair<Key, Val>& pair )
  {
    return pair.second == m_val;
  }
private:
  Val m_val;
};
 
int main()
{
  std::map<std::string, int> map;
  
  map["hello"] = 0;
  map["hell"]  = 1;
  map["world"] = 0;
 
  std::map<std::string, int>::iterator it;
 
  for( ; map.end() != ( it = std::find_if( map.begin(), map.end(), 
                                           _equal<std::string, int>( 1 ) ) ); )
  {
    map.erase( it );
  }
 
  for( it = map.begin(); it != map.end() ; ++it )
  {
    std::cout << it->first << " ";
  }
 
}
Добавлено через 2 минуты
Цитата Сообщение от grizlik78 Посмотреть сообщение
SomeMap::iterator oldpos = pos;
* * * * * * * * ++pos;
* * * * * * * * coll.erase(oldpos)
побольшей части неочевидно, что копия итератора будет валидна после удаления элемента из мапа
в листе например все итераторы как правило после удаления становятся невалидными
0
Эксперт С++
 Аватар для grizlik78
2383 / 1667 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
03.07.2011, 12:18
Цитата Сообщение от alex_x_x Посмотреть сообщение
в листе например все итераторы как правило после удаления становятся невалидными
Вот здесь не согласен, давай доказательства. По моим сведениям (хоть бы из того же Джосьютиса) удаление в списке не влияет на ссылки на другие элементы.
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,980
03.07.2011, 12:28
alex_x_x, да и я почти то же самое говорил страницы три назад

Цитата Сообщение от grizlik78 Посмотреть сообщение
заменяет такую, более громоздкую, конструкцию:
Ну так-то да, но всё равно как-то стрёмно... Мне даже думается, что это тот самый случай, когда лучше бы громоздкую конструкцию написать, за то точно работающую...
0
Эксперт С++
 Аватар для grizlik78
2383 / 1667 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
03.07.2011, 12:36
easybudda, да они обе точно работающие, и в обоих случаях возникает желание "пооптимизировать", вынеся инкремент из условия.
С тем что удалять лучше вообще не так я не только не спорю, но и сам так удалять не стал бы (если надо просто удалить элементы с заданным значением). Не стал бы так делать, уверен, и автор книги. Способ удаления не является рекомендованным, как тут говорилось, он просто корректный и обращает внимание на то, как не надо действовать, если потребность удаления в процессе итерации. А именно, не надо инкрементировать итератор после удаления. В книге ведь не только этот фрагмент, там ещё и слова написаны, и пример некорректного кода есть. А выдранный из контекста код действительно выглядит подозрительным.
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
03.07.2011, 12:37
grizlik78, попробовал - и правда работает
получается
C++
1
2
  list.erase( it++ );
  std::cout << *( it );
и
C++
1
2
  it = list.erase( it );
  std::cout << *( it );
работает одинаково
все это изза того, что природа итераторов библиотеки неочевидна, видимо они жестко привязаны к контейнерам
0
Эксперт С++
 Аватар для grizlik78
2383 / 1667 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
03.07.2011, 12:50
Цитата Сообщение от alex_x_x Посмотреть сообщение
в листе например все итераторы как правило после удаления становятся невалидными
Вот, 23.2.2.3 list modifiers
iterator erase(iterator position);
iterator erase(iterator first, iterator last);
void pop_front();
void pop_back();
void clear();
Effects: Invalidates only the iterators and references to the erased elements.
Иначе мне будет вообще непонятно, зачем нужны списки.

Добавлено через 9 минут
Цитата Сообщение от alex_x_x Посмотреть сообщение
все это изза того, что природа итераторов библиотеки неочевидна, видимо они жестко привязаны к контейнерам
Конечно привязаны. Не зря же они берутся от контейнеров: vector<>::iterator, list<>::iterator, map<>::iterator, и т.д.
STL вообще опасная штука, если пользоваться ей не зная как там всё работает.
0
4866 / 3287 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
03.07.2011, 14:14
Цитата Сообщение от easybudda
А вот с понятными названиями переменных и сам код понятнее становится.
понятные названия, очевидный алгоритм - всё должно быть
чем меньше размышлений, тем больше свободного места в "оперативной памяти" под что-нибудь ещё
0
Заблокирован
03.07.2011, 14:17  [ТС]
Цитата Сообщение от accept Посмотреть сообщение
Сообщение от Bers
Скилл слишком маленький.
в инглише ?
С99 - 6.5.2.4 postfix
С99 - 6.5.3.1 prefix
Не понятно, как там навигация устроенна.
Как вы ссылочку нашли?
0
03.07.2011, 14:27

Не по теме:

Цитата Сообщение от accept Посмотреть сообщение
чем меньше размышлений, тем больше свободного места в "оперативной памяти" под что-нибудь ещё
Я вот только на некоторых своих знакомых замечаю - чем больше они у себя в "оперативной памяти" свободного места оставляют, тем её с годами меньше становится. Мозг её то ли чем-то другим занимает, то ли просто сохнет... Для компактности... :D

0
Заблокирован
03.07.2011, 14:52  [ТС]
любопытную ссылочку на Хаббаре нашёл, но постить её здесь боюсь, ибо могут счесть за рекламу.

Суть в том, что автор тамошней статьи проанализировал несколько различных известных проектов (например Миранда) на ошибки. Результат анализа опубликовал, и привел рекомендации, как писать код так, что бы подобных ошибок не допускать.


И вот имейте ввиду - это реальные проекты, которые писали реальные сеньоры, а не какие нибудь джуниоры.

И как это часто бывает, в комментариях к статье, автора начали критиковать.
Потом и вовсе - пришёл один из разработчиков Миранды (он в первой части статьи в основном запостил наиболее зверские косяки Миранды)

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

Начались разборки, тесты, доказательства. Оказалось что на разных компиляторах код ведёт себя по разному...

C++
1
2
3
4
  char *(ImgIndex[64]);
  ...
  memset(&ImgIndex,0,sizeof(&ImgIndex)); //очень далеко не факт, что обнулит массив.
                               //моя студия обнулит только первый элемент.
А я вот вообще не понял, почему сеньор из Миранды не написал попроще:
memset(ImgIndex,0,sizeof(ImgIndex));

А вообще, код Миранды ужассен в плане читабельности. Так что не удивительно....


easybudda, вторая часть его статьи начинается так:

1. Не используйте тернарную операцию '?:' в составных выражениях

Помните свою 3х этажную рекурсию?))

Если меня за это не поругают, могу запостить ссылочку.
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
03.07.2011, 15:33
ImgIndex и &ImgIndex дают одинаковый адрес
sizeof(ImgIndex) и sizeof(&ImgIndex) дают естесственно разный размер
он просто ошибся

сейчас в коде миранды просто
C++
1
2
3
4
                w1=ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_WEB);
                c1=ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_CLIENT);
 
                memset( ImgIndex, 0, sizeof( ImgIndex ) );
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,980
03.07.2011, 15:41
Цитата Сообщение от Bers Посмотреть сообщение
memset(&ImgIndex,0,sizeof(&ImgIndex)); //очень далеко не факт, что обнулит массив. //моя студия обнулит только первый элемент.
И правильно сделает. Оператор & перед ImgIndex за каким рожном стоит?
На сколько понял, создали массив из 64 указателей, так и обнуляем его не мудрствуя лукаво...
C
1
2
char * ImgIndex[64];
memset(ImgIndex,0,sizeof(ImgIndex));
Так должно отработать.

Цитата Сообщение от Bers Посмотреть сообщение
Не используйте тернарную операцию '?:' в составных выражениях
Помните, что на сарае написано? А там брёвна лежат. Если всё, что при неправильном использовании может вызывать ошибки, не использовать, получится эдакий С в духе Эллочки-Людоедки из 12 стульев. Жуть, короче...


Опоздал немного...
0
4866 / 3287 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
04.07.2011, 02:51
Цитата Сообщение от Bers
Не понятно, как там навигация устроенна.
Как вы ссылочку нашли?
open-std -> C -> standards -> latest

C++ - 10Mb
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21285 / 8310 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
04.07.2011, 11:17
Цитата Сообщение от easybudda Посмотреть сообщение
Я вот только на некоторых своих знакомых замечаю - чем больше они у себя в "оперативной памяти" свободного места оставляют, тем её с годами меньше становится. Мозг её то ли чем-то другим занимает, то ли просто сохнет... Для компактности...
В контексте данного спора у тебя почему-то всегда перекос идёт в сторону новичков, лентяев, идиотов и т.п. А твои оппоненты говорят про нормальных людей в нормальной команде

Цитата Сообщение от Bers Посмотреть сообщение
1. Не используйте тернарную операцию '?:' в составных выражениях
На мой взгляд категорических заявлений такого вида делать не стОит. Есть случаи, когда оно оправдано, а есть случаи, когда так лучше не делать. Хз зачем ввели операцию ?:, но я подозреваю, что для того, чтобы можно было использовать в макросах (чтобы было как бы единственное присваивание, чего нельзя сделать с if-then-else)
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,980
04.07.2011, 12:41
Цитата Сообщение от Evg Посмотреть сообщение
В контексте данного спора у тебя почему-то всегда перекос идёт в сторону новичков, лентяев, идиотов и т.п. А твои оппоненты говорят про нормальных людей в нормальной команде
Ну давайте по пунктам. Во-первых новички. Испытывать какую-то неприязнь к ним просто по тому, что знают чуть меньше - глупо. Изначально мозг у всех свободен от знаний. Ну так и они разные бывают. Пальцем тыкать не буду, но есть здесь на форуме молодой человек. Появился год назад примерно. Толком ничего не знал, но горел желанием. А теперь у него у самого есть, чему научиться. Ну а можно с первых дней работы и до пенсии нажимать определённый набор кнопок, и не дай бог, что изменится... Про лентяев и идиотов говорить вообще не хочется. А по поводу

Цитата Сообщение от Evg Посмотреть сообщение
А твои оппоненты говорят про нормальных людей в нормальной команде
Я знаю, что такое производственная рутина. Люди, как на конвеере, по шаблону каждый свою детальку клепают. Тогда конечно каждое лишнее движение не то, чтоб не желательно, а прям таки опасно. В одном месте криво пошло, в другом совсем застряло. Но это же не значит, что "точить детальки по незатейливому шаблону" - true style, и любая вольность - зло. Вот Вы опять всё в кучу сваливаете - у меня и в мыслях не было считать команду профессиональных программистов сборищем идиотов и лентяев. Вот только то программирование, которым в командах занимаются - скука смертная (вот потому, наверное, и не стал я профессиональным программистом).
Но есть совсем другой стиль программирования. Нет, не ставящий себе целью сделать программу похожей на шифровку шпионскую. Вот это я до Вас всё никак донести не могу. Программа может быть не только "простой и ясной для понимания", она же может предельно чётко (без рюшичек) и разумно компактно излагать смысл задуманного, вот правда, чтоб его понять прийдётся поднапрячься. За то с осмыслением задуманного, оцениваешь и на сколько красиво человек свою мысль изложил. Вот тогда это интересная программа. А Вы мне всё - "нам думать некогда, мы детальки точим". Да точите себе на здоровье, я ж не против...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
04.07.2011, 12:41

Unique ptr в классе
Добрый вечер, есть ли реальное решение придерживаться правилу нуля и иметь в классе std::unique_ptr ?

Разница в byte ptr
Подскажите пожаулйста: в чем разница между cmp byte ptr, 0 и cmp ECX, 0 и cmp , 0 Copyre: push offset...

Что такое qword ptr gs
Есть инструкция jmp qword ptr gs: Каким образом мне понять куда она прыгает (конкретный адрес)? Это указатель на что? И что такое gs

Что делает операция PTR
Привет всем! У меня вопрос к опытным программистам в ассемблере х86. Недавно в документации по Турбо Паскалю 6.0 в секции использования...

Что означает конструкция *(*ptr + j)
void board(int Mas) { for(int j=0;j&lt;=99;j++) { cout&lt;&lt;*(*Mas+j)&lt;&lt;&quot; &quot;; } } можете объяснить че из себя...


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

Или воспользуйтесь поиском по форуму:
180
Ответ Создать тему
Новые блоги и статьи
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru