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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 1, средняя оценка - 5.00
zss
Модератор
Эксперт С++
6530 / 6092 / 2007
Регистрация: 18.12.2011
Сообщений: 15,844
Завершенные тесты: 1
#1

Распространенные ошибки - C++

21.09.2014, 17:33. Просмотров 63752. Ответов 60
Метки нет (Все метки)

Оглавление

Ошибки этапа компиляции
Программа не компилируется или компилируется с предупреждениями.
  1. Попытка модифицировать константу через указатель
  2. Неправильное понятие приведения
  3. Лишняя точка с запятой
  4. Отсутствие точки с запятой после определения классового типа
  5. Отсутствие возврата значения из функции
  6. Использование комментариев в #define
  7. Компилятор не находит iostream.h
  8. Внутри switch ошибка Case bypasses initialization of a local variable
  9. Передача двумерных массивов и указателей в функцию
  10. Не удается открыть файл stdafx.h
  11. Ошибка "unresolved external symbol _WinMain@16"
  12. Ошибка "This function or variable may be unsafe"
Ошибки этапа выполнения
Программа прекращает работу с сообщением об ошибке
  1. Выделение памяти без дальнейшего освобождения или неверное освобождение
  2. Возврат ссылки/указателя на локальную переменную
  3. Использование неинциализированной переменной
  4. Выход за пределы массива
  5. Ошибки при использовании функции scanf()
  6. Работа с локальной копией объекта, вместо работы с самим объектом
  7. Интерпретация одиночного char символа как символьной строки
  8. Ошибка преобразования: type ** в const type **
Неправильное поведение программы на этапе исполнения
Программа исполняется, но не так, как хотелось.
  1. Неожиданное закрытие окна
  2. "Неожиданное" целочисленное деление в арифметических выражениях
  3. Ошибки в логических выражениях
  4. Лишняя точка с запятой
  5. switch без break
  6. Сравнение вещественных чисел при вычислениях
  7. Сравнение char массивов
  8. Использование чисел, записанных в других системах счисления
  9. Проверки на принадлежность значения определенному интервалу
  10. Неверный аргумент тригонометрических функций
  11. Сравнение знаковой переменной с беззнаковой
  12. Использование запятой для отделения дробной части
  13. Забытое выделение тела цикла for, while и операторов if else
  14. Определение размера массива, переданного в качестве аргумента функции
  15. Порядок вычисления аргументов при вызове функции
  16. Некорректное использование логических переменных
  17. Вычисленное значение косинуса не совпадает с ожидаемым
  18. Локальная переменная экранирует переменную с таким же именем из вышестоящей области видимости
  19. Неправильное использование memset
Алгоритмические ошибки
Ошибки, допущенные при разработке алгоритма
  1. Двойная перестановка строк или элементов массива
  2. Использование символа цифры вместо числа
Ошибки ввода-вывода
  1. Оставление символа '\n' в потоке ввода
  2. Ошибки при использовании функции scanf()
  3. При работе с fgetc чтение файла обрывается при достижении буквы 'я'
  4. При считывании из файла последний элемент читается дважды
Ошибки, связанные с отклонением от стандарта языка
  1. Неверный тип функции main()

Ошибки проектирования АТД (классов).
  1. Вызов виртуальной функции из конструктора
  2. Отсутствие точки с запятой после определения класса/структуры
  3. Неверный вызов конструктора базового класса из конструктора производного
  4. Неверный порядок при инициализации
  5. Нарушение правила ТРЕХ.
  6. Отсутствие виртуального деструктора в базовом классе
  7. Неправильное обращение к конструктору по умолчанию
  8. Не очевидные моменты с вызовом конструктора базового класса
  9. Неявно объявленный конструктор по умолчанию
  10. Перегрузка оператора >>
Ошибки при использовании STL контейнеров
  1. Невалидные ссылки/указатели, при перемещении объектов
  2. Ошибки связанные с итераторами (кэширование размера контейнера)
  3. Ошибки связанные с итераторами (удаление элементов по итератору в циклах)
  4. Ошибки связанные с итераторами (префикс-постфиксные инкременты при удалении элементов в цикле)
25
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.09.2014, 17:33
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Распространенные ошибки (C++):

Вывести самые распространенные мужские и женские имена - C++
Имеется массив записей о студентах, каждая из которых включает поля: фамилия, имя, отчество, пол, возраст, курс. Разработать программу,...

Вывести самые распространенные женские и мужские имена - C++
Помогите решить задачу пожалуйста! Написать программу, которая формирует файл записей данной структуры Type Student=Record ...

Найти ошибки в коде и исправить эти ошибки (Наследование) - C++
Вот в общем 3 файла, изучаю наследование на примере односвязного и двусвязного списков: list.h (inline) #pragma once class list...

Найти ошибки в коде и исправить эти ошибки - C++ - C++
Судя по вываливающейся ошибки, идет двойное освобождение памяти. У самого не получается отловить откуда. A.h #pragma once ...

Найти ошибки в коде и исправить эти ошибки - C++
Есть у меня вот такой код: #include <iostream> using namespace std; class A{ private: int* a; size_t size_; ...

Распространенные ошибки - C (СИ)
Оглавление Ошибки этапа компиляции (В процессе компиляции выдается либо сообщение об ошибке, либо предупреждение) - Попытка...

60
daslex
1285 / 529 / 109
Регистрация: 02.08.2011
Сообщений: 2,750
04.10.2014, 14:16 #31
Интерпретация одиночного char символа как символьной строки

Начинающие программисты иногда воспринимают отдельный тестовый символ как строку из одного значения.
char c; - отдельный символ, занимающий 1 байт в памяти.
char str[256] - строка символов длиной не более 255, которая всегда должна заканчиваться признаком окончания строки - числом ноль.

Из-за этого различия вполне реально столкнутся с проблемой преобразования при работе со строками.
Простейший пример
C++
1
2
3
4
5
char ch = 'z';
char S[255] = "TestString__";
 
strcat( S, (char *)ch ); // попытка объединить строку с символом
std::cout << S << "\n";
Здесь используется явное приведение типа char к char *,
т.к. написавший подразумевает символ строки как строку в 1 символ., но в этом-то и ошибка.
______________________

Для подобного преобразования строки нужно выполнить явное присвоение нужного символа и добавление терминального нуля:
C++
1
2
3
4
5
6
char ch = 'z';
char S[255] = "TestString__";
int L = strlen( S );
S[L] = ch;
S[L + 1] = 0;
std::cout << S << "\n";

Вариант решения - создать массив в 2 символа. Принудительно забить сам символ и признак окончания в этот массив, после чего использовать этот массив вместо изначального символа.

C++
1
2
3
4
5
6
7
8
char ch = 'z';
char S[255] = "TestString__";
char temp[2] = "";
temp[0] = ch;
temp[1] = 0; // Обязательно
 
strcat( S, temp );
std::cout << S << "\n";
Итак всегда помните, что строка символов заканчивается нулем!
0
MrGluck
Модератор
Эксперт CЭксперт С++
7491 / 4606 / 692
Регистрация: 29.11.2010
Сообщений: 12,590
06.10.2014, 16:38 #32
Отсутствие виртуального деструктора в базовом классе.
Класс по умолчанию генерирует деструктор, но при этом он не является виртуальным. Отличие виртуального деструктора в том, что он предполагает освобождение ресурсов не только базового класса, но и всех производных. Ниже пример, явно демонстрирующий проблему:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
 
class A
{
public:
    A() { std::cout << "A()"; }
    ~A() { std::cout << "~A()"; }
};
 
class B : public A
{
public:
    B() { std::cout << "B()"; }
    ~B() { std::cout << "~B()"; }
};
 
int main()
{
    A * p = new B;
    delete p;
    // выведет A()B()~A()
}
При размещении объекта производного класса на стеке, вызов деструкторов будет правильным, а вот при динамическом (как выше), произойдёт неполное освобождение ресурсов т.к. деструктор не виртуальный. Таким образом, виртуальный деструктор нужен для правильного полиморфного удаления объектов.

Для исправления ошибки в примере выше достаточно сделать деструктор класса A виртуальным,
строку 7 поменять на
C++
1
virtual ~A() { std::cout << "~A()"; }
Во избежание проблем всегда следует как минимум:
1. При наличии хотя бы одного виртуального метода объявлять виртуальным и деструктор.
2. Также его надо явно объявлять виртуальным, если класс предполагается в будущем сделать базовым.

Майерс советует делать виртуальным деструктор всегда, кроме тех случаев, когда есть веские причины этого не делать.
В некоторых компиляторах (mingw) существует флаг -Weffc++, который выдаёт предупреждение по данной ошибке.

P.S. в "правиле трёх" надо бы также описать данный случай как исключение из правил т.к. при необходимости явного объявления виртуального деструктора это вовсе не значит, что нужно описывать конструктор копий или оператор присваивания. ЕМНИМ, в оригинале говорится, что если в классе идёт работа с памятью, то необходимо явно объявить три вещи...
2
XZentus
201 / 199 / 41
Регистрация: 06.10.2013
Сообщений: 552
31.10.2014, 23:02 #33
Порядок вычисления аргументов при вызове функции.

Недавно ловил ошибку в собственном коде.

C
1
2
3
4
5
6
7
8
9
10
11
12
/* Глобальная переменная, единственное место хранения количества хэшей.
Т.е. если бы была ошибка где-то в алгоритме, здесь, скорее всего, было бы левое значение */
int nhash = 0; 
 
// ...
 
int main( int argn, char * argv[] ) {
    // ...
    // nkeyhash в своих недрах активно использует nhash, при чем только увеличивая значение
    printf( "\n%lli\t%d\n", nkeyshash( argv[1], argv[2] ), nhash );
    return 0;
}
Глупая ошибка, но час потратил, пока не понял, почему nhash всегда показывал 0.
Хотя, если бы там действительно был ноль на момент завершения работы, программа выдавала бы неверное значение nkeyshash(...)

P.S. Кстати, результат не зависел от ключей оптимизации.

Т.о. имейте ввиду, что нельзя рассчитывать на то, что вычисление значений аргументов в списке параметров функции выполняется слева-направо.
1
MrGluck
Модератор
Эксперт CЭксперт С++
7491 / 4606 / 692
Регистрация: 29.11.2010
Сообщений: 12,590
31.10.2014, 23:45 #34
Сегодня наткнулся на подобное (код понятное дело упрощён и добавлены действия, эмулирующие работу):
C++
1
2
3
4
5
6
7
8
9
10
11
bool GetImageSize( const char * fileName, int & width, int & height )
{
    width = height = 42;
    return true;
}
 
int main ()
{
    int width = 0, height = 0;
    std::cout << GetImageSize( "tmp.jpg", width, height ) << " " << width << " " << height;
}
Проблема в том, что до ; значения остаются в рамках одной инструкции, т.е. не меняют своё значение. Возможно, UB, надо вырезку из стандарта прикрепить, а времени сейчас нет.

Добавлено через 52 секунды
Это в продолжение к проблеме XZentus, просто код, на мой взгляд, более реален.
0
XZentus
201 / 199 / 41
Регистрация: 06.10.2013
Сообщений: 552
01.11.2014, 08:51 #35
Цитата Сообщение от MrGluck Посмотреть сообщение
Возможно, UB, надо вырезку из стандарта прикрепить, а времени сейчас нет.
Неуточняемое поведение.

Кликните здесь для просмотра всего текста
6.5.2.2 Function calls
Constraints
1 The expression that denotes the called function 92) shall have type pointer to function
returning void or returning a complete object type other than an array type.
2 If the expression that denotes the called function has a type that includes a prototype, the
number of arguments shall agree with the number of parameters. Each argument shall
have a type such that its value may be assigned to an object with the unqualified version
of the type of its corresponding parameter.
Semantics
3 A postfix expression followed by parentheses () containing a possibly empty, comma-
separated list of expressions is a function call. The postfix expression denotes the called
function. The list of expressions specifies the arguments to the function.
4 An argument may be an expression of any complete object type. In preparing for the call
to a function, the arguments are evaluated, and each parameter is assigned the value of the
corresponding argument. 93)
5 If the expression that denotes the called function has type pointer to function returning an
object type, the function call expression has the same type as that object type, and has the
value determined as specified in 6.8.6.4. Otherwise, the function call has type void.
6 If the expression that denotes the called function has a type that does not include a
prototype, the integer promotions are performed on each argument, and arguments that
have type float are promoted to double. These are called the default argument
promotions. If the number of arguments does not equal the number of parameters, the
behavior is undefined. If the function is defined with a type that includes a prototype, and
either the prototype ends with an ellipsis (, ...) or the types of the arguments after
promotion are not compatible with the types of the parameters, the behavior is undefined.
If the function is defined with a type that does not include a prototype, and the types of
the arguments after promotion are not compatible with those of the parameters after
promotion, the behavior is undefined, except for the following cases:
— one promoted type is a signed integer type, the other promoted type is the
corresponding unsigned integer type, and the value is representable in both types;
— both types are pointers to qualified or unqualified versions of a character type or
void.
7 If the expression that denotes the called function has a type that does include a prototype,
the arguments are implicitly converted, as if by assignment, to the types of the
corresponding parameters, taking the type of each parameter to be the unqualified version
of its declared type. The ellipsis notation in a function prototype declarator causes
argument type conversion to stop after the last declared parameter. The default argument
promotions are performed on trailing arguments.
8 No other conversions are performed implicitly; in particular, the number and types of
arguments are not compared with those of the parameters in a function definition that
does not include a function prototype declarator.
9 If the function is defined with a type that is not compatible with the type (of the
expression) pointed to by the expression that denotes the called function, the behavior is
undefined.
10 There is a sequence point after the evaluations of the function designator and the actual
arguments but before the actual call. Every evaluation in the calling function (including
other function calls) that is not otherwise specifically sequenced before or after the
execution of the body of the called function is indeterminately sequenced with respect to
the execution of the called function. 94)
11 Recursive function calls shall be permitted, both directly and indirectly through any chain
of other functions.
12 EXAMPLE
In the function call
C
1
(*pf[f1()]) (f2(), f3() + f4())
the functions f1, f2, f3, and f4 may be called in any order. All side effects have to be completed before
the function pointed to by pf[f1()] is called.
0
Somebody
2791 / 1602 / 147
Регистрация: 03.12.2007
Сообщений: 4,199
Завершенные тесты: 1
01.11.2014, 10:37 #36
Sequence points :-( Во времена C++14...
Тут уже не просто аргументы вычисляются "in any order", а вообще "Value computations and side effects associated with different argument expressions are unsequenced".
C++14 1.9, абзац 10
15 Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [ Note: In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. —end note ] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [ Note: Value computations and side effects associated with different argument expressions are unsequenced. —end note ] Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.9 Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. [ Example: Evaluation of a new expression invokes one or more allocation and constructor functions; see 5.3.4. For another example, invocation of a conversion function (12.3.2) can arise in contexts in which no function call syntax appears. —end example ] The sequencing constraints on the execution of the called function (as described above) are features of the function calls as evaluated, whatever the syntax of the expression that calls the function might be.
9) In other words, function executions do not interleave with each other.
0
ValeryS
Модератор
6707 / 5116 / 482
Регистрация: 14.02.2011
Сообщений: 17,189
09.12.2014, 11:18 #37
Использование комментариев в #define

Комментарии в #define
C++
1
2
#define VAR  5 // так делать не рекомендуется 
#define VAR  5 /* так можно */
Почему?

Потому что предкомпилятор видя VAR подставляет все что за ней, и вот такое выражение:
C++
1
int x = VAR;
превратит его в первом случае в
C++
1
int x = 5 // так делать не рекомендуется ;
потерялась точка с запятой, ушла в комментарии.

Во втором случае:
C++
1
int x = 5  /* так можно */;
это уже не страшно.
2
Tulosba
:)
Эксперт С++
4397 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
09.12.2014, 11:33 #38
Цитата Сообщение от ValeryS Посмотреть сообщение
превратит его в первом случае в
Ну, а проверить хотя бы? Комменты в препроцессор не попадают, на то они и комменты.
http://ideone.com/cKjv9L

Добавлено через 34 секунды
Цитата Сообщение от ValeryS Посмотреть сообщение
сам только что нарвался
Хотелось бы узнать: где?
1
ValeryS
Модератор
6707 / 5116 / 482
Регистрация: 14.02.2011
Сообщений: 17,189
09.12.2014, 11:49 #39
Цитата Сообщение от Tulosba Посмотреть сообщение
Ну, а проверить хотя бы?
разумеется пример утрированный, чтобы показать проблему
в таком примере отработает и то и другое
Цитата Сообщение от Tulosba Посмотреть сообщение
Хотелось бы узнать: где?
Keil библитеки STM, макросы вложенные один в другой и все вместе в третий в четвертый
решил прокомментировать (//) и поперли ошибки

но вот тебе пример, тоже утрированный, никто в здравом уме такое писать не будет
многострочный макрос

C++
1
2
#define VAR /*так можно прокоментировать*/  \
   /*и так можно прокомментировать */5
а как прокомментировать двумя слэшами?
0
Tulosba
:)
Эксперт С++
4397 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
09.12.2014, 12:20 #40
Цитата Сообщение от ValeryS Посмотреть сообщение
в таком примере отработает и то и другое
Значит, такой пример не состоятельный. И нужен другой для подтверждения проблемы.
Цитата Сообщение от ValeryS Посмотреть сообщение
а как прокомментировать двумя слэшами?
Максос по своей природе должен быть однострочным, для этого и добавляют "\" в конце каждой псевдостроки, когда он слишком длинный и хочется тем не менее избежать горизонтальной прокрутки. А учитывая то, что комментарий в виде двойных прямых слешей комментирует всё оставшееся до конца строки, то и располагать его надо в конце макроса, т.е. в твоем случае за пятеркой:
C++
1
2
#define VAR /*так можно прокоментировать*/  \
   /*и так можно прокомментировать */5 // comment
1
Evg
Эксперт CАвтор FAQ
18248 / 6373 / 438
Регистрация: 30.03.2009
Сообщений: 17,640
Записей в блоге: 28
09.12.2014, 12:23 #41
Что в каком порядке делается. Комментарии заменяются на пробелы до того, как выполняется запоминание макросов

Код
ISO/IEC 9899:1999 (E)
 
5.1.1.2 Translation phases
 
...
2. Each instance of a backslash character (\) immediately followed by a new-line
character is deleted, splicing physical source lines to form logical source lines.
Only the last backslash on any physical source line shall be eligible for being part
of such a splice. A source file that is not empty shall end in a new-line character,
which shall not be immediately preceded by a backslash character before any such
splicing takes place.

3. The source file is decomposed into preprocessing tokens 6) and sequences of
white-space characters (including comments). A source file shall not end in a
partial preprocessing token or in a partial comment. Each comment is replaced by
one space character. New-line characters are retained. Whether each nonempty
sequence of white-space characters other than new-line is retained or replaced by
one space character is implementation-defined.

4. Preprocessing directives are executed, macro invocations are expanded, and
_Pragma unary operator expressions are executed. If a character sequence that
matches the syntax of a universal character name is produced by token
concatenation (6.10.3.3), the behavior is undefined. A #include preprocessing
directive causes the named header or source file to be processed from phase 1
through phase 4, recursively. All preprocessing directives are then deleted.
4
ValeryS
Модератор
6707 / 5116 / 482
Регистрация: 14.02.2011
Сообщений: 17,189
07.01.2015, 21:26 #42
Некорректное использование логических переменных
часто встречаю такую вешь
C++
1
2
3
4
5
6
bool tmp;
// здесь что то делается с tmp
if ( tmp == true )
{
    ...
}
if ( tmp == true ) и есть тавтология (тождественно истинное высказывание, инвариантное относительно значений своих компонентов, по - русски повтор)
рассмотрим подробнее
if срабатывает если в скобках ИСТИНА (true) если ЛОЖЬ (false) то управление передается ветке else
теперь смотрим tmp==true tmp имеет значение true результат true, if исполняется
tmp==true tmp имеет значение false результат false, исполняется else
как видим результат равен tmp
поэтому достаточно, и необходимо написать if ( tmp ) вместо if ( tmp == true )
ошибка не так безобидна, как она кажется
в WinApi до сих пор используется тип BOOL это макрос int
и в разных версиях компилятора TRUE имело значение и 1 и -1 (все биты единицы)
а в языке C, C++ принято соглашение все что не 0 это ИСТИНА 0 это ЛОЖЬ
теперь представим себе что в переменную типа
BOOL tmp записали 1 это по соглашениям языка все равно что tmp=ИСТИНА
но TRUE определен как -1
и условие if ( tmp == TRUE ) не сработает
тогда как if ( tmp ) сработает правильно
в старых MSDNах писали, не знаю как сейчас, нельзя сравнивать с TRUE
только с FALSE (поскольку оно однозначно 0)
т.е наша запись должна выглядеть так
C++
1
if ( tmp != FALSE )
или так
C++
1
if ( tmp )
1
MrGluck
Модератор
Эксперт CЭксперт С++
7491 / 4606 / 692
Регистрация: 29.11.2010
Сообщений: 12,590
09.01.2015, 00:17 #43
Цитата Сообщение от ValeryS Посмотреть сообщение
36. Некорректное использование логических переменных
Таки распространенная ошибка? Не видел чтобы множество новичков использовали BOOL из WinAPI. И тем более сравнивали так:
C++
1
if ( tmp == TRUE )
И заявленная вами же фраза
Цитата Сообщение от ValeryS Посмотреть сообщение
ошибка не так безобидна, как она кажется
никак не относится к выражению
Цитата Сообщение от ValeryS Посмотреть сообщение
if ( tmp == true )
Условие выше никогда не является ошибочным. Избыточным да, но не ошибочным.
1
hoggy
6697 / 2879 / 494
Регистрация: 15.11.2014
Сообщений: 6,478
Завершенные тесты: 1
10.01.2015, 01:49 #44
Невалидные ссылки/указатели, при перемещении объектов.

Пример: Реаллок вектора:

История болезни:

1. В вектор напихиваются объекты по значению.
2. Из вектора срисовывается ссылка/указатель на какое либо из его значений.
3. В вектор напихивают ещё некоторое количество объектов.
4. В какой то момент резерв памяти иссякает, и вектор реалочится - расширяет буфер, переносит туда свои объекты. В результате объекты меняют адрес.

5. Выданные наружу ссылки/указатели становятся недействительными, но никто никого об этом не предупредил.
6. Обращение по невалидному указателю/ссылки - крэш времени выполнения.

Искать причину таких вылетов затруднительно, потому что:
1. Авария обычно происходит далеко от места причины аварии.

2. В целях оптимизации, для вектора любят резервировать память (vector::reserve).
В результате в большинстве случаев резерва хватает, и вектор редко реалочится.
В результате баги долгое время могут оставаться незамеченными,
а когда стреляет - довольно сложно сказать почему (сп пункт 1)

Пример:
http://rextester.com/AWJSK45012

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
39
40
41
42
43
// Title of this code
// g++  4.8.2
 
#include <iostream>
#include <vector>
 
struct isome
{
    virtual ~isome() {}
    virtual void foo() = 0;
};
 
struct some : isome
{
    int val = 10;
 
    virtual void foo() {
        val += 10; std::cout << "val = " << val << '\n';
    }
};
 
int main()
{
    std::cout << "Hello, world!\n";
 
    std::vector <some> vec;
 
    vec.emplace_back();
 
    some & s = vec.back();
    s.foo();
 
    vec.push_back( some() );
    vec.push_back( some() );
    vec.push_back( some() );
    vec.push_back( some() );
    vec.push_back( some() );
    vec.push_back( some() );
    vec.push_back( some() );
    vec.push_back( some() );
 
    s.foo();
}
Подобную ошибку можно выделить в целый класс ошибок связанных с "неперемещаемостью объектов".
Потому что помимо вектора, она может встречаться в самых разных ситуациях.

Например: создали std::function на метод класса, объект переехал, делегат покрэшел весь процесс.
И тп.
5
zss
Модератор
Эксперт С++
6530 / 6092 / 2007
Регистрация: 18.12.2011
Сообщений: 15,844
Завершенные тесты: 1
19.01.2015, 10:19  [ТС] #45
Неправильное обращение к конструктору по умолчанию.
C++
1
2
3
4
5
6
7
8
9
10
class A
{
public:
    A() {}
    ...
};
 
...
 
A a();
Объявляется переменная a типа A.
Круглые скобки ставятся для явного указания, что нужен конструктор без параметров.

Однако, такая конструкция интерпретируется как объявление (прототип) функции без параметров
с именем a, которая возвращает значение типа A.
Правильным будет такое объявление:
C++
1
A a;
4
19.01.2015, 10:19
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.01.2015, 10:19
Привет! Вот еще темы с ответами:

безопасность и распространенные ошибки - Perl
Тут наткнулся на очень интересные тексты: http://werad.narod.ru/articles/programm6.html http://werad.narod.ru/articles/programm9.html...

.NET 2.x Распространенные ошибки SEO и ASP.NET 2.0 - C# ASP.NET
Здравствуйте, существуют несколько СЕО проблем при использовании ASP.NET, ниже я опишу эти проблемы, нужно найти простое и эффективное...

Самые распространенные строки - Delphi
type Mytype = record name:string; surname:string; end; var Students:Mytype; MyFile:file of Mytype; ...

Вирус блокирует выход на сайт вк и другие распространенные сайты - Удаление вирусов
я чайник поэтому если что то не загрузилось..напишите пожалуйста, и помогите... второй день вожусь с этим. Hosts чистый, drweb выявил один...


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

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

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