Создатель C++ ответил на 5 самых популярных вопросов по C++ со Stack Overflow
Почему отсортированный массив обрабатывается быстрее, чем не отсортированный? Что за оператор −−>? Есть ли исчерпывающий список книг по C++? Чем отличаются ссылки от указателей? Как пройтись по словам в строке? — Отвечает Бьёрн Страуструп.
16К открытий16К показов
Бьёрн Страуструп (дат. Bjarne Stroustrup) — технический сотрудник и управляющий директор Morgan Stanley в Нью-Йорке, профессор Колумбийского Университета и создатель C++.
Авторы курса Learn C++ из Codecademy взяли у Страуструпа интервью. В отдельном материале можно почитать его рассуждения про значимость языка и советы всем начинающим программистам. А здесь мы перевели его ответы на 5 самых популярных вопросов по C++ за всё время.
— Почему отсортированный массив обрабатывается быстрее, чем не отсортированный?
Посмотреть этот вопрос на Stack Overflow, на русском Stack Overflow
— Очень похоже на вопрос с собеседования. Это и правда так? Как это можно проверить? Отвечать на вопрос про производительность, не проведя перед этим измерения — плохая идея, так что нам важно понять, как проводить эти измерения.
Итак, я проверил сортировку массива миллиона целых чисел:
Прим. перев. В оригинальном вопросе автор находил сумму элементов массива и на отсортированных данных это получалось почти в 10 раз быстрее. Страуструп вместо сложения взял ещё одну сортировку и проверил, что быстрее отсортируется: уже упорядоченный массив или рандомный. Звучит глупо, но на самом деле ответ универсальный и применим к любым операциям с массивами. Если данные упорядочены, то работать, скорее всего, будет быстрее.
Я запустил код несколько раз, чтобы убедиться. Действительно, то, о чём говорится в вопросе — правда. Я использовал следующий код:
По крайней мере это правда для моего компилятора, стандартной библиотеки С++ и моих настроек оптимизатора. Разные реализации могут привести и приведут к разным результатам. Есть исследование на эту тему (должно легко гуглиться), и в большинстве реализаций компилятора С++ будет наблюдаться такой же эффект.
Первая причина такого поведения лежит в механизме предсказания ветвлений (branch prediction): основная операция в алгоритме сортировки — сравнение if (v[i] < pivot]) ...
или его эквивалент. Для упорядоченной последовательности это сравнение будет всегда истинно, тогда как в рандомном массиве выбор ветки будет случайным.
Другая причина в том, что если массив уже упорядочен, нам не нужно перемещать элементы на правильные позиции. Из-за этих небольших деталей мы и получаем разницу во времени в 5 или 6 раз.
Алгоритм быстрой сортировки (да и алгоритмы сортировки вообще) — это целое исследование, которым занимались величайшие умы computer science. Хорошая функция для сортировки подразумевает как выбор правильного алгоритма, так и учёт особенностей реализации железа.
Если вы хотите писать эффективный код, вам нужно хотя бы немного знать об архитектуре компьютеров.
— Что за оператор −−> в С++?
Посмотреть этот вопрос на Stack Overflow, на русском Stack Overflow
— Это старый хитрый вопрос. В С++ нет оператора −−>.
Рассмотрим такой код:
Выглядит так, как будто и правда есть оператор −−>
, и если правильно объявить переменные p
и m
, то код даже скомпилируется и запустится:
Это означает: если p−−
больше чем m
(а это так), то надо сравнить результат (true)
с нулём. Ну, true != 0
, так что результат всего выражения — false
, и функция f()
не вызовется. Другими словами:
Пожалуйста, не тратьте много времени на подобные вопросы. Они сбивали с толку новичков ещё до того, как появился С++.
— Исчерпывающий список книг по С++
Посмотреть этот вопрос на Stack Overflow, на русском Stack Overflow
— К сожалению, такого списка нет. И не может быть. Разным людям нужна разная информация, у них разный бэкграунд, а сам язык С++ постоянно развивается.
Я поискал в интернете — там целый набор подобных списков, это сбивает столку. Одни серьёзно устарели, другие изначально плохи. Беспомощный новичок запутается в поисках хорошей книги.
Вам и правда нужна именно книга для изучения С++, потому что техники, которые делают этот язык эффективным, не очень-то легко почерпнуть из отдельных заметок в блогах. И, конечно, информация там бывает ошибочной, устаревшей, с плохим объяснением. Кроме того, там часто фокусируются на продвинутом материале о нововведениях и пропускают необходимые основы.
Рекомендую мою книгу «Программирование. Принципы и практика с использованием C++» для тех, кто только начинает изучать программирование, и «A Tour of C++» для тех, кто уже программирует и хочет больше узнать о современном С++. Люди с хорошей математической базой могут начать с книги Питера Готтшлинга «Современный C++. Для программистов, инженеров и ученых».
Когда вы начнёте использовать C++ по-настоящему, вам понадобится набор правил, чтобы научиться лучшим практикам. Для этого на гитхабе есть C++ Core Guidelines.
За короткими ёмкими объяснениями отдельных особенностей языка и функций стандартной библиотеки рекомендую идти на сайт cppreference.
Бьёрн Страуструп: не существует исчерпывающего списка книг по C++, это бред.
Тем временем редакторы Tproger:
— Чем отличаются ссылки от указателей в С++?
Посмотреть этот вопрос на Stack Overflow, на русском Stack Overflow
— И ссылка, и указатель хранят в памяти машинный адрес. Разница в том, как они используются.
Чтобы инициализировать указатель, вы даёте ему адрес объекта:
Чтобы считывать и записывать значение через указатель, надо использовать оператор разыменования (*
):
Если присвоить одному указателю другой, они оба будут указывать на один и тот же объект:
Заметьте, что один и тот же указатель может в разное время своей жизни указывать на разные объекты. Это ключевое отличие от ссылок. Ссылка привязана к конкретному объекту в момент своего создания и не может позже ссылаться на что-то ещё.
Для ссылок происходит неявное разыменование. Вы инициализируете ссылку объектом, и в ссылке сохраняется адрес этого объекта:
Оператор new
возвращает указатель, так что нам нужно разыменовать его перед присваиванием.
Чтобы считывать и записывать значения через ссылку, нам надо просто использовать имя этой ссылки (без явного разыменования):
Когда мы присваиваем одну ссылку другой, то будет скопировано именно значение по ссылке, а не сама ссылка:
Что ссылки, что указатели часто используются в качестве аргументов функции:
Указатель может быть и nullptr
, так что нам нужно следить за тем, чтобы он в принципе на что-то указывал. А ссылка всегда относится к какому-то объекту.
— Как пройтись по словам в строке С++?
Посмотреть этот вопрос на Stack Overflow, на русском Stack Overflow прямого аналога не нашли
Надо использовать stringstream
. Но как определить, что такое «слово»? Скажем, в предложении «Я устал переводить эту статью.» последнее слово «статью» или «статью.»?
Прим. перев. Перевели строки в коде на кириллицу, компилируется на C++14 (clang 8.0).
Если пунктуации нет вообще, то всё просто:
Или даже так:
По умолчанию оператор >>
пропускает пробелы. Если же нам нужен настраиваемый набор разделителей слов, код будет посложнее:
Здесь функция d
служит для определения, является ли символ разделителем, и я возвращаю ""
(пустую строку) чтобы обозначить, что слов для возвращения не было.
Если у вас есть библиотека Range из C++20, можете использовать split_view
вместо того, чтобы писать это всё самостоятельно.
16К открытий16К показов