Форум программистов, компьютерный форум, киберфорум
BinaryBlade
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Краткое сравнение С++ 98 и С++ 11

Запись от BinaryBlade размещена 25.05.2023 в 10:27
Показов 3746 Комментарии 0

Краткое сравнение “старого” С++ от “нового”



Введение



Что же я имею ввиду под определением старый и новый С++ ? На самом деле всё элементарно.
У С++ как и у любого другого языка программирования имеются версии релиза – это обусловлено его развитием: добавлением новых функций, расширением стандартной библиотеки, повышением производительности, устранением ошибок предыдущих версий и т.д.
Согласно статьям Википедии последняя актуальная и рабочая версия языка, является - C++ 20.
В данной статье я не буду говорить про последнюю версию С++. Я хочу отметить наиболее важные и основные отличия С++ 98 и С++ 11.



Почему С++ 98 и С++ 11


Вероятно, многие разработчики до сих пор используют исходный стандарт языка С++ 98. Что не удивительно, так как многие обучающие ресурсы (книги, видеоматериалы) или старые проекты, созданные до 2011 года, до сих пор поддерживаются 98-м стандартом.
Но язык не стоит на месте, и поэтому на замену с++ 98 пришёл с++ 11, который собрал в себе наиболее важные изменения за всё время существования языка. Именно поэтому я буду делать сравнение между этими версиями.
Но к сожалению, я не смогу охватить тот объём информации, который состоит из всех новых возможностей версии с++ 11 и постараюсь отделить всё самое важное и крайне необходимое из этой версии. Поехали!



Встроенные типы данных


Исходя из таблицы можно заметить, что особой разницы в типе данных не наблюдается.

типы с++98 с++11
int, short int, long int + +
long long - +
char, wchar_t + +
char16_t, char32_t - +
bool + +



Ключевое слово auto


В 11 версию языка была добавлена возможность использовать ключевое слово auto.
auto – позволяет инициализировать тип переменной или лямбда–выражения во время компиляции.
Пример
:


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class A {
public:
int varA;
 
A (int a) {varA = a}
 
};
 
auto var_int {1};  // int
auto var_bool {true}; // bool
auto var_char {"1"};  //  char
auto A = new A(1); // class A
}

Ещё одна из важных особенностей auto, это перебор коллекции из любого контейнера STL в цикле for без явного указания типа элемента коллекции:

C++
1
2
3
4
5
6
7
8
9
std::vector<int> nums = {0,1,2,3,4,5,6,7};
for (auto &e : nums)
{std::cout<< e;}  // 01234567
 
for (auto e : nums)
{std::cout<< e;}  // 01234567
 
for (auto &e : {0,1,2,3,4,5,6,7})
{std::cout<< e;} // 01234567

Удобство:
  • Нет нужды переживать за правильное использование нужного типа данных
  • Функция объявленная с auto вернёт результат, даже если тип данных возвращаемого значения изменится
  • auto позволяет сократить написание кода



Список инициализаторов initializer_list


initializer_list – является классом, на основе которого можно создать объект, для инициализации элементов массива определенного типa.

Пример:



C++
1
2
3
4
5
6
7
8
9
10
11
void Init(std::initializer<int> list){
 
for(auto &e : list) {std::cout << e;} //10011101010010
 
}
 
int main(){
 
Init({1,0,0,1,1,1,0,10,10,0,1,0});
 
}

Замечу, что если речь идёт о передаче списка инициализации объектам класса или структуры, то необходимо соблюдать передачу, соответствующую порядку определению членов структуры.

Пример:



C++
1
2
3
4
5
6
7
8
9
10
11
//c++ 11
 
MyStruct mstr_cpp_11 = {11,true,'\n'};
// теперь сравните с вариантом ниже
 
// с++ 98
MyStruct mstr_cpp_98;
 
mstr_cpp_98.number = 11;
mstr_cpp_98.active = false;
mstr_cpp_98.end = '\n';

Удобство:
  • Сокращение написания кода
  • Улучшена читаемость кода



Ключевое слово typedef и using

typedef – используется для определения альтернативного имени типа данных, либо как синоним для спецификации шаблона с указанием всех его параметров,

к примеру:


C++
1
2
typedef short int INT16;
INT16 number = 89; // short int


Но для шаблонов такой способ не подойдёт:

C++
1
2
3
4
template <typename First, typename Second, int third>
class SomeType;
 
typedef SomeType<OtherType, Second, 8> TypedefName; // Ошибка компиляции!

И наконец в с++ 11 была добавлена возможность создавать синоним имени шаблона с использованием следующего синтаксиса:

C++
1
2
3
4
template <typename First, typename Second, int third>
class SomeType;
 
using TypedefName = SomeType<OtherType, Second,8> // ОК!


Также для простых типов

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using FLOAT = float;
using PFLOAT = float*;
 
int main(){
 
using std::cout,std::endl;
 
FLOAT PI = 3.14;
 
PFLOAT p_PI;
 
 p_PI = &PI; 
 
}

Удобство:
  • Возможность создавать псевдоним для типа шаблона
  • Улучшена читаемость кода



Ключевое слово sizeof

До 11 версии языка, оператор sizeof можно было использовать только для простых типов и объектов. Например, следующая конструкция не сработает для с++ 98 ( и с++ 03):

C++
1
2
3
4
5
6
7
8
9
10
struct MyStruct{
int number;
};
 
int main(){
using std::cout, std::endl;
 
cout << sizeof(MyStruct::number) << endl;  // Ошибка компиляции!
 
}
[FONT="Microsoft Sans Serif"]Для версии 11 эта проблема решена. Тот же код сможет выполнится на с++ 11.[/FONT


Нулевой указатель nullptr


До появления с++ 11, разработчики использовали в качестве константы нулевого указателя макрос NULL (0), который указывал на область в памяти, где гарантировано отсутствуют какие-либо данные.

Проблема заключается в том, что константа 0 играла двойную роль целого числа и нулевого указателя. Это влияло на проектирование кода с использованием перегрузки функции,

например:


C++
1
2
3
4
5
6
7
void GetType(char *) {std::cout<< "char *";}
void GetType(int) {std::cout<< "int";}
 
int main(){
GetType(0);     // вывод:  int
GetType(NULL); // вывод: int     "так как NULL является тоже целым числом 0, то вызов GetType(char *) не произойдёт"
}
В С++ 11 эта проблема была решена с помощью константы nullptr:

C++
1
2
3
4
5
void GetType(char *) {std::cout<< "char *";}
void GetType(int) {std::cout<< "int";}
 
int main(){
GetType(nullptr);     // вывод:  char *
Удобство:
- Решает проблему с перегрузками функций





Ключевое слово constexpr


сonstexpr – это спецификатор типа, который гарантирует, что выражение является константным (const). Был добавлен в с++ 11 с целью инициализации константных выражений ( функций,объектов, переменных ) на этапе компиляции, для определения внешних массивов или значений перечислений.

Например:


C++
1
2
3
4
5
6
7
8
9
10
11
12
constexpr int GetNum() {
return 100;
}
 
int main(){
 
using std::cout,std::endl;
 
int arr[GetNum() + 7];
 
cout << sizeof(arr) << endl; // 428
}


В данном случае код сработает, так как выражение GetSize() + 7 заведомо является константным за счёт использования constexpr. Без указания этого спецификатора, выражение GetSize() + 7 не гарантирует, что оно является константным. То есть компилятору на данный момент неизвестно вернёт ли функция константу или нет.

Удобство:
  • Любые выражения можно сделать константными
  • Выражения с constexpr вычисляются во время компиляции (если это возможно) либо во время выполнения



Ключевое слово final


С++11 позволяет запрещать в классах-наследниках переопределение определенных методов. Достигается это за счет применения спецификатора final рядом с сигнатурой метода.


C++
1
2
3
4
5
6
7
8
9
class Base {
public:
virtual void doSomething(int x) final;
};
 
class Derived : public Base{
public:
virtual void doSomething(int x); // Ошибка компиляции! 
};
Данный спецификатор также позволяет запрещать наследование от некоторого класса.

Например:


C++
1
2
class Base final {};
class Derived : public Base {}; // Ошибка компиляции!
Спецификатор final издавна существует в Java. Наконец он появился и в C++.

Удобство:
  • Защита от переопределения виртуальной функции
  • Защита от наследования



Выражение lambda

Лямбда выражения – определяют объект анонимной функции непосредственно в месте, где она и вызывается. Чаще всего такие выражения используют для инкапсуляции данных, передаваемых в какой-либо метод или функцию, откуда она и будет в итоге вызвана в качестве callback.
Простой пример:


C++
1
2
3
4
5
6
7
8
9
using std::cout,std::endl;
 
int main(){
 
auto get_word = [](){return "Hello world!";}
 
cout << get_word() << endl;
 
}

Более сложный пример:


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int A = 1;
int B = 2;
int C = 3;
 
auto GetWord = [=,  &B](string _word){
 
A += 2; // Ошибка компиляции! Изменение значения не сработает, захват переменной только для чтения
B += 2;  // Изменение значения сработает, захват B осуществлялся по ссылке
C += 2; // Ошибка компиляции! Изменение значения не сработает, захват переменной только для чтения
 
cout << "Вызов в анонимной функции: " <<endl;
cout << A << endl << B << endl << C << endl;
cout << _word << endl; 
 
};

Удобство:
  • Эффективно повышает читабельность программы
  • Уменьшение количества строк кода
  • Отсутствие каких либо новых строк или имен



Умные указатели (std::unique_ptr)

И последнее важное новшество в с++ 11 – это умные указатели.
Любой программист C++, вероятно, согласится с тем, что одним из самых сложных аспектов языка является ручное управление памятью. Охват всех возможных случаев и путей возврата (включая исключения) может оказаться сложной задачей даже для языковых экспертов, часто с ужасными последствиями утечек памяти или ошибок сегментации. C++11 предоставляет невероятный набор инструментов, позволяющий почти устранить эту проблему, сохраняя при этом мощь и гибкость, которые делают C++ таким замечательным языком.

Пример с простым указателем:



C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A{
public:
void ShowText()
{
 
cout << "Hello world!" << endl;}
 
};
 
int main(){
 
A* ptr_obj = new A(); // создаём объект в куче
 
ptr_obj->ShowText(); // вызываем метод объекта
 
delete ptr_obj;  // удаляем объект
}

Вроде бы всё хорошо, но есть одна проблема. Что произойдёт если ShowText() по каким – либо причинам, выбросит исключение? Тогда управление не дойдёт до delete и память, занятая ptr_obj не освободится.
Поэтому сообществом разработчиков с++ было принято решение не использовать delete для ручного освобождения памяти.
В следующем примере наглядно демонстрируется использование std::unique_ptr:


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <memory> // обязательная библиотека для подключения умных указателей
 
class A{
public:
void ShowText()
{
 
cout << "Hello world!" << endl;}
 
};
 
int main(){
 
unique_ptr<A> ptr_obj(new A()); // создаём объект в куче
 
ptr_obj->ShowText(); // вызываем метод объекта
 
// объект ptr_obj автоматически удалится за счёт встроенного delete в unique_ptr
 
}
Даже если ShowText() выбросит исключение, память занятая ptr_obj всё равно освободится.

Удобство:
  • Автоматическое освобождение динамической памяти
  • Уменьшение количества ошибок программистов



Выводы


С++ необъятный и постоянно развивающейся язык программирования. В каждой новой версии языка появляется больше возможностей, удобств, средств автоматизаций, алгоритмов, сокращений и т.д. В этой статье конечно же многие детали были опущены и упрощены, для более поверхностного понимания того, как язык может развиваться и меняться. Надеюсь я смог обогатить ваш мозг небольшой крупицей информации по С++.


Благодарю за прочтение статьи!
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
Модель по догадкам
anaschu 25.08.2026
Прошло две недели. Я уже рассказывал, как разговаривал с сотрудниками у сортировки и как понял, что главная ветка — не про приёмку, а про отбор. Но тогда я думал, что понял механику. На этой неделе я. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru