Форум программистов, компьютерный форум CyberForum.ru

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

Войти
Регистрация
Восстановить пароль
 
Хохол
Эксперт C++
475 / 443 / 13
Регистрация: 20.11.2009
Сообщений: 1,292
#1

Почему не происходит ошибка при обращении к недопустимому индексу - C++

27.06.2010, 22:46. Просмотров 804. Ответов 9
Метки нет (Все метки)

C++
1
2
3
4
5
6
7
#include <string>
 
int main()
{
    std::string s;
    s[0];
}
Исключения не происходит. Внимание вопрос: я схожу с ума, я не знаю цпп или мне нагло врет VS?
Думаю, все же третье. Никогда раньше такого не встречал. При обращении к s[1] исключение исправно выбрасывается.
Запускаю в VS 2008. Может кто знает, что за фигня?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.06.2010, 22:46
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Почему не происходит ошибка при обращении к недопустимому индексу (C++):

При обращении к индексу двумерного массива char программа вылетает с ошибкой - C++
Программа вылетает с ошибкой на 66й строке. Почему?((( // Task_1.cpp : Defines the entry point for the console application. // ...

Почему происходит ошибка при описании массива? - C++
int setSize; cout &lt;&lt; &quot;How many elements would you have? &quot;; cin &gt;&gt; setSize; const int getSize = setSize; int a; ошыбка тут int...

При обращении к структуре из класса возникает исключение:нарушение прав доступа при записи. Почему? - C++
Структура Test описана в классе ABC: class ABC{ struct Test { int get_i() { return i; } void put_i(int j) { i = j;} ...

Разница в обращении к массиву по индексу и по указателю - C++
Дочитал до главы &quot;Указатели&quot; и возникли вопросы, если у кого найдется время подскажите Вот пример: #include &lt;iostream&gt; using...

Почему происходит ошибка времени выполнения? - C++
прошу помощи в поиске ошибки! уже 2часа пытаюсь найти и никак... Тоже задание по структуре. над ошибкой уже 2 час сижу не могу понять...

Подскажите почему происходит ошибка в вычислении - C++
При введении следующих параметров (60 2.3 3) выходит ответ 4rub. 13cop. хотя должен выдавать 4rub. 14cop. , не могу разобраться почему...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Nick Alte
Эксперт С++
1636 / 1008 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
28.06.2010, 10:36 #2
Оператор индексации [] в STL проектируется так, чтобы не отставать от обычной индексации по скорости. То есть, он не проверяет передаваемые ему индексы и не выбрасывает исключения. Этим занимается at(). Так что я склоняюсь ко второму варианту из предложенных.
Хохол
Эксперт C++
475 / 443 / 13
Регистрация: 20.11.2009
Сообщений: 1,292
28.06.2010, 10:50  [ТС] #3
Оператор [] всю жизнь все проверял и выбрасывал исключения. s[1] в данном примере выбрасывает исключение.

Добавлено через 2 минуты
http://codepad.org/bC2VIMF6

Добавлено через 2 минуты
Попробуйте запустить этот код у себя.
Nick Alte
Эксперт С++
1636 / 1008 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
28.06.2010, 15:20 #4
Документация на STL утверждает иное. И уж извините, Хохол, но в этом вопросе я скорее доверюсь документации.
Код из basic_string.h библиотеки из состава GCC:
C++
1
2
3
4
5
const_reference operator[] (size_type __pos) const
{
    _GLIBCXX_DEBUG_ASSERT(__pos <= size());
    return _M_data()[__pos];
}
Как видим, есть только проверка assert'ом, которая включается только при компиляции в отладочном режиме.
easybudda
Модератор
Эксперт CЭксперт С++
9530 / 5523 / 932
Регистрация: 25.07.2009
Сообщений: 10,602
28.06.2010, 15:52 #5
Цитата Сообщение от Хохол Посмотреть сообщение
Исключения не происходит.
да вроде и не должно бы. При создании объекта класса string как минимум один элемент в нём уже присутствует (тот самый, на который итератор возвращаемый функцией end() указывает), вот Вам и s[0], а вот s[1] и в правду нету, потому и исключение...
C++
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <string>
 
int main(){
    std::string s;
    char c;
    c = s[0];
    std::cout << (int)c << std::endl;
    
    return 0;
}
выведет 0
Nick Alte
Эксперт С++
1636 / 1008 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
28.06.2010, 15:55 #6
На всякий случай напомню всем, кто заинтересуется: на пару к оператору индексации в индексируемых STL-контейнерах добавляют функцию at(), которая делает то же самое, но индекс как раз-таки проверяет и std::out_of_range выбрасывает в случае чего.
Так что код
C++
1
2
3
4
5
6
#include <string>
int main()
{
        std::string s;
        s.at(0);
}
выбросит то самое исключение std::out_of_range
Хохол
Эксперт C++
475 / 443 / 13
Регистрация: 20.11.2009
Сообщений: 1,292
28.06.2010, 15:59  [ТС] #7
А почему ж на кодпаде мой код фейлится?

Добавлено через 28 секунд
А у них ассерт другой почему-то
Код
Assertion '__pos < size()' failed.
Nick Alte
Эксперт С++
1636 / 1008 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
28.06.2010, 16:13 #8
А у них вполне могла бы быть и реализация STL другая. Стандарт предъявляет только определённые требования к поведению, а уж реализуются они у кого как. В Visual Studio будет другой ассерт.

Тем не менее, ассерт как раз тот же самый. В тексте библиотеки упоминается следующее:
// allow pos == size() as v3 extension
(допустить равенство pos и size() в качестве расширения v3)
В режиме pedantic в неконстантном индексировании используется строгое сравнение pos < size(), которое мы и видим в кодепадовском сообщении.

Ну и мы видим, что на кодепаде таки в отладочную конфигурацию компилируют, чтобы с дополнительными проверками. И в режиме pedantic.
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
25.12.2012, 13:03 #9
Цитата Сообщение от Nick Alte Посмотреть сообщение
Как видим, есть только проверка assert'ом, которая включается только при компиляции в отладочном режиме.
Но всё таки проверка есть, а режим мог быть и отладочный.

Добавлено через 3 минуты
Вот только при индексации с ноля <=size даст допустимость индекса сразу за концом строки. Видимо данная реализация std::string хранит на один символ больше, чем длина строки и реально последний символ всегда терминальный ноль. Тогда исключение на [0] и не должно выскакивать, так как в любой, даже пустой, строке всегда будет как минимум один символ, так как терминальный ноль - тоже символ и он есть в каждой, даже пустой, строке.
silent_1991
Эксперт С++
4963 / 3039 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
29.12.2012, 09:58 #10
taras atavin, это зависит не от того, что строка там хранит. Она может изначально хоть "Hello, World!" хранить, но пока в неё что-то не записано, размер у неё 0. И поэтому оператор индексации, если бы он должен был выбрасывать исключение, выбросил бы его. Но по стандарту оператор индексации работает без проверок, метод at() - с проверками.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.12.2012, 09:58
Привет! Вот еще темы с ответами:

Почему происходит ошибка undefined reference to hgeCreate - C++
Всем привет. Я новичок по C++ и недавно решил освоить разработку игр. Скачал с интернета 2D движок для графики HGE, однако никак не могу...

Ошибка при обращении к классу - C++
Есть класс для хранения элементов, к которым должен быть доступ из других классов - решил объявить как глобальный: Items.h: class...

Ошибка при обращении к указателю: maybe you mean to use '->' - C++
#include &lt;windows.h&gt; #include &lt;stdio.h&gt; #include &lt;conio.h&gt; struct book { char avtor; //fio char caption; ...

Ошибка при обращении к элементу строки *s - C++
Помогите, пожалуйста. Задача: описать рекурсивную функцию digits(s) целого типа, находящую кол-во цифр в строке s без использования...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
29.12.2012, 09:58
Ответ Создать тему
Опции темы

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