Две недели назад в Джэксонвилле встречался комитет стандарта ISO C++. Сегодня я хочу представить короткую сводку и написать о революционном решении, принятом на собрании в Джэксонвилле. Для получения дополнительной информации я рекомендую к прочтению статью C++ больше не будет иметь указатели. Комитет по стандартизации языка принял решение о том, что указатели будут объявлены устаревшими в C++20 и с большой долей вероятности будут удалены из C++23.
Откровенно говоря, то, что кажется революционном, — всего лишь последний шаг длинной эволюции.
Эволюция указателей в C++
Указатели существуют в C++ с самого начала. Мы получили их из C. С самого начала развития C++ всегда была тенденция сделать управление указателями более безопасным без значительных потерь.
В C++98 мы получили std::auto_ptr
для выражения исключительного владения. Но std::auto_ptr
имел большой изъян. Когда вы копирует std::auto_ptr
, владение ресурсом передавалось копии. Копирование выглядело как перемещение. Изображение ниже показывает неприятное поведение std::auto_ptr
.
Это было очень плохо, приводило к множеству серьёзных багов. Поэтому мы получили std::unique_ptr
в C++11, и объявили std::auto_ptr
устаревшим в C++11, и окончательно удалили из C++17. Дополнительно мы получили std::shared_ptr
и std::weak_ptr
в C++11 для управления владением. Вы не можете копировать, но можете перемещать std::unique_ptr
, и если копируете или присваиваете std::shared_ptr
, счётчик ссылающихся указателей увеличивается. Посмотрите сюда:
Начиная с C++11 C++ имеет многопоточную библиотеку. Это делает управление std::shared_ptr
достаточно сложным, потому что std::shared_ptr
по определению разделяемое, но не потоко-безопасное. Только контрольная часть со счётчиками является потоко-безопасной, но не доступ к адресу контролируемого ресурса. Это значит, что изменение счётчика — атомарная операция, но вы не имеете гарантии, что ресурс будет удалён ровно один раз. По этой причине мы получаем в C++20 атомарные умные указатели: std::atomic_shared_ptr
и std::atmic_weak_ptr
. Про детали предложений комитета стандартизации читайте здесь: Атомарные умные указатели.
Теперь переходим к более интересным частям будущих стандартов C++20 и C++23. Указатели будет объявлены устаревшими в C++20 и удалены из C++23. Скажем три слова: Нет Новому New (NNN).
std::unique_ptr спасёт нас
Но подождите, как же догма C++: Не платить за то, что вам не нужно. Как мы сможем программировать без указателей? Просто используйте std::unique_ptr
. Из своего дизайна std::unique_ptr
такой же быстрый и экономный, как и обычный указатель, и имеет явное преимущество — автоматическое управление ресурсом.
Ниже простой тест производительности.
// all.cpp
#include <chrono>
#include <iostream>
static const long long numInt= 100000000;
int main(){
auto start = std::chrono::system_clock::now();
for ( long long i=0 ; i < numInt; ++i){
int* tmp(new int(i));
delete tmp;
// std::shared_ptr<int> tmp(new int(i));
// std::shared_ptr<int> tmp(std::make_shared<int>(i));
// std::unique_ptr<int> tmp(new int(i));
// std::unique_ptr<int> tmp(std::make_unique<int>(i));
}
std::chrono::duration<double> dur= std::chrono::system_clock::now() - start;
std::cout << "time native: " << dur.count() << " seconds" << std::endl;
}
Эта программа выделяет и освобождает память для 100 миллионов int
. Я использую указатели, std::shared_ptr
и std::unique_ptr
в двух вариациях. Я компилирую программу с и без максимальной оптимизации в Linux и в Windows. Получаются такие числа:
Две вариации std::unique_ptr
на Linux и Windows показывают такую же производительность, как обычные указатели. За деталями этого теста обратитесь к моей прошлой статье: Потребление памяти и производительность умных указателей.
Семантика владения
Честно говоря, мы используем указатели и, в частности, обычные указатели очень часто. Вопрос, должны ли вы использовать указатель, сводится к следующему: Кто владелец? К счастью, с помощью кода мы можем чётко выразить это.
- Локальные объекты. Рантайм C++ как владелец автоматически управляет жизнью таких ресурсов. То же самое относится к глобальным объектам или членам класса. Справочники сводят это к области видимости.
- Ссылки: я не владелец. Я только обеспечиваю, что ресурс не может быть пустым.
- Обычные указатели: я не владелец. Я только ссылаюсь на ресурс, если он есть. Я не должен удалять ресурс.
- std::unique_ptr: я исключительный владелец ресурса. Я могу явно освободить мой ресурс.
- std::shared_ptr: я разделяю ресурс с другими
std::shared_ptr
. Я могу явно удалить мой разделяемый ресурс, если он больше никому не нужен. - std::weak_ptr: я не владелец ресурса, но я могу временно разделять ресурс при вызове моего метода
std::weak_ptr::lock
.
Нам нужно будет изменить только одну из шести практик использования указателей и мы рады следующему шагу в развитии C++.
Комментарии (134)
Anton3
01.04.2018 14:05+2Прочитал заголовок, обрадовался, перечитал заголовок, посмотрел на дату, взгрустнул. Согласен с подходом Rust, когда указатели, конечно, не deprecated, но почти на все случаи жизни существуют ссылки и другие безопасные аналоги. Проблема недостатка безопасных аналогов как раз находится в процессе решения: string_view, span, observer_ptr.
encyclopedist
02.04.2018 11:33+1string_view
иspan
не являются безопасными. Объект, на который они ссылаются, может быть удалён или перемещён, а вы и не заметите. Пример:
std::string_view sv = function_returning_string();
Тут
string_view
будет dangling, потому что ссылается на временную строку, которая сразу будет уничтожена.
kmu1990
01.04.2018 14:35+3Забавно, 5 статей (no-new-new, cpp-will-no-longer-have-pointers, no-pointers, raw-pointers-are-gone, deprecating-pointers) ссылающихся друг на друга по кругу — довольно хорошо ребята подготовились. Если бы еще c isocpp.org договорились, вобще бы умора была.
Fails
01.04.2018 18:34Да, я сегодня утром тоже заметил) в тг-чат крестовый кидали оригинал английский )
DistortNeo
01.04.2018 14:45-1А если серьёзно, то C++ не хватает для умных указателей нормального синтаксиса.
Зачем писатьstd::unique_ptr<T>
, когда можно писатьT^
?
Зачем писатьstd::make_unique<T>(...)
, когда можно писатьnew T^(...)
?mayorovp
01.04.2018 15:49+2А как вы будете обозначать shared_ptr? А weak_ptr? И еще какой-нибудь com_ptr, нестандартный но иногда очень нужный? Спецсимволов же не хватит…
DistortNeo
01.04.2018 17:13+1Достаточно краткой записи только для unique_ptr и shared_ptr. Редкоиспользуемые случаи же спецсимволами покрывать не нужно. Мне C++ очень нравится, но многословность несколько выбешивает.
AllexIn
01.04.2018 17:46+2Сделайте макрос, если очень хочется и не будет многословности.
А лезть с синтаксическим сахаром в стандарт не нужно. Особенно с аргументацией «мне нравится unique_ptr, для его давайте схара, а остальные не надо, я ими не пользуюсь»Jamdaze
02.04.2018 07:09Говориш не надо тебе сахара? Может и range based for тебе не надо?
Только из за добавления сахара с++ стал юзабельным. С отвращением вспоминаю всё что было до с++03\с++11.
Необходимость синтаксиса для «умных» указателей это следствие наличия в языке:
а) Стандартного аллокатора, который по умолчанию используется для всего,
б) Деструкторов — суть и соль языка,
в) Собственно, необходимости работать с указателями.
new должен возвращять умный указатель на объект или блок памяни (начало и конец), иначе мы не далеко уходим от голимого Си.
gbg
02.04.2018 08:25Который из умных указателей он должен возвращать? Самый нафаршированный, и потому медленный shred_ptr, или чего попроще?
Antervis
02.04.2018 08:43new — не такое часто используемое слово, чтобы экономия 10 знаков в сравнении с make_shared/make_unique была существенной. range based for нужен больше потому, что с ним ошибок меньше.
Jamdaze
04.04.2018 09:44Возможно вы меня не так поняли. У нас есть язык, и программирование на нём построено вокруг различных идиом в основе которых лежит использование деструкторов. В этом языке есть алакатор по умолчанию и есть оператор создания объекта, являющийся частью языка а не стандартной библиотеки.
new — часть языка, и для того чтобы язык выглядел более самодостаточным, было бы логичным что new возвращяет безопасный указатель, с однозначным намёком что этот указатель надо будет освободить, после использования.
Chaos_Optima
02.04.2018 14:49Для себя писал макросы чтобы можно было так писать
struct MKSHARED { template<class T> std::shared_ptr<T> operator*(T* ptr) { return std::shared_ptr<T>(ptr); } } MK_SHARED; #define shared MK_SHARED* auto p = shared new SomeClass(); auto v = unique new SomeClass();
FoxCanFly
01.04.2018 19:13Если тащить все в синтаксис языка вместо реализации в библиотеках, через некоторое время язык превратится в свалку из странных синтаксических конструкций, но хватать их все равно не будет. А запомнить, какая из комбинаций знаков препинания создает shared_ptr, какая weak, а какая — вообще std::thread будет невозможно никому
deviant_9
01.04.2018 21:09+3Сломается обратная совместимость, ибо new T^(...) — валидная конструкция с вполне определённым смыслом:
struct T{}; T *operator^(T *lhs, T) { return lhs; } int main() { T x; T *ptr = new T^(x); }
Синтаксис C++ и так перегружен по части всевозможного использования закорючек — в стандарте в некоторых случаях приходится явно разрешать неоднозначность интерпретации тех или иных конструкций (например, является ли T() типом функции, возвращающей значение типа T, или созданием временного объекта типа T).DistortNeo
01.04.2018 21:54+3в стандарте в некоторых случаях приходится явно разрешать неоднозначность интерпретации тех или иных конструкций
Это следствие отсутствия ключевого слова "function".
deviant_9
01.04.2018 23:52В шаблонах даже без функций есть неоднозначности между объявлениями и выражениями — как, например, в случае a::b * c или a::b<c> d, где a — параметр шаблона.
laphroaig
01.04.2018 15:31+20Еще к 23 году уберут постфиксную форму ++ ввиду ее неэффективности, а сам стандарт переименуют ++c23
Wild__Recluse
01.04.2018 15:31+3Как хорошо, что это шутка. У меня даже сердце остановилось.
TargetSan
01.04.2018 17:02+2В каждой шутке есть доля шутки. Указатели позволяют слишком много. Ссылки обрезаны по самое небалуйся. reference_wrapper имеет почти нужную семантику, но, как ни смешно, слишком длинное имя. А optional из стандарта не имеет sentinel value оптимизации, из-за чего проигрывает голым указателям и по размеру, и по совместимости. К тому же слишком "легко" превращается в голое значение. В общем не хватает чего-то вроде
optional<ref<T>>
, имеющего почти нулевой оверхед по сравнению с указателем (за вычетом ассёртов в отладочном режиме).crea7or
01.04.2018 17:36+1Возьмите c++ core guidelines и пишите в строгом соответствии с ними — никто же не мешает.
TargetSan
01.04.2018 17:48Если вы про owned/notnull — они дают какую-то семантику только в паре со статическим чекером, который их понимает. Последний раз такой чекер был только в Visual Studio. Т.е. его работоспособность даже в VS Build Tools под вопросом. В целом же, как я вижу, С++ всё больше требуется отдельный независимый от компилятора DSL для описания статических проверок :)
Miron11
01.04.2018 19:24Чего… Визуальная Студия все свои правила из библиотеки берёт. Но ассобенно сомневающиеся могут и саму Студию с командной строки запустить. В серьёзном проэкте всегда нужен свой статический анализ кода. У меня на проэкте гуру пишет базы для проэкта 25-й год. Она меня целует, за статический анализ. Когда глава фирмы прибегает и ждет, чтобы выдали новую процедуру такое пишут, что никаким опытом и знаниями волнение не защитить.
crea7or
01.04.2018 17:39+1C++ core guidelines: Resources management:
TargetSan
01.04.2018 17:49+3Это всё хорошо, но не описывает borrowed pointers и not-null pointers независимо от компилятора.
DistortNeo
01.04.2018 20:05+1Насчёт 11: предпочитаю всегда писать
std::unique_ptr<T>(new T(...))
, чемstd::make_unique<T>(...)
. Причина простая: в первом случае работают подсказки IDE, во втором случае — нет.
reversecode
01.04.2018 19:42Если это не шутка, то совсем не понятно что означает «new removed»
Удалить его вряд ли смогут, скорее всего пометят в рекомендации что использования new в коде, муветон, не более.
А иначе не вижу что предлагается в замен, умные указатели это не то, они память тоже не с астрала черпают
Tippy-Tip
02.04.2018 01:05Я поверил статье пока не дошел до тэгов… :)
AFAIK, тэги собирались удалять с Хабра (честно признаюсь: не ищу статьи по тэгам), но в данном случае тэги сыграли свою роль. Поэтому считаю что тэги на Хабре нужно оставить.
P.S. С прошедшими Днём Архивов и Днём Дураков!
geekmetwice
02.04.2018 03:52-2Смех — смехом, но «развитие» С++ именно, что похоже на чью-то дебильную, 1-апрельскую шутку! Или же на известный квартет, меняющийся местами. Что бы в С++ ни ввели, безбожно уродливый синтаксис, вкупе с «совместимостью неуклюжей ООП модели», оставляет язык без шансов. Ну попрыгают ещё старпёры со своими «умными указателями», ещё пару сотен «списиалистов» выпустят ВУЗы, но язык так и останется «трупом страуса». Он просто ТУПИК.
Комитет, вместо проедания денег, лучше бы взялся за D — вот уж кому не помешали бы деньги и дополнительные ресурсы! Ди решил множество проблем Сипипей, но комитет старых пердунов продолжает насиловать стюардессу, год от года становясь всё более смешным.Whuthering
02.04.2018 08:59Выше уже были комментарии про растовцев:
фанаты раста в тредах про с++ как веганы на барбекю пикнике. Орут громче всех, а кто вас звал то?
В каждый пост про С++ приходят фанаты раста и начинают объяснять как «правильно» надо программировать.
так вот, к фанатам D, как ни странно, то же самое полностью подходит :)
yurrig
04.04.2018 10:33Соберите свой комитет по D, добейтесь авторитета в индустрии, народ к вам потянется, компиляторы напишет под ваш стандарт, компании начнут свой код на ваш D переносить. <<Тогда и поговорим>>
JBMurloc
02.04.2018 09:05Пошутили, блин. Давно такого дикого срача не видел в комментариях. Как же все напряглись-то.
fukkit
02.04.2018 09:46Кроме того, чтобы скомпилировать старую программу с помощью новых версий компилятора Microsoft без ошибок к сигнатуре каждой функции будет необходимо добавлять спецификатор "__unsafe_please_do_not_remove"
VioletGiraffe
02.04.2018 12:47Интересно, 55 плюсjв у статьи — это от тех, кто понял шутку, или от тех, кто не понял? :)
asadullin_timur
02.04.2018 13:10-1никто никуда переходить не будет :) если с++ станет удобнее, он только закрепит свои позиции популярного языка, тем более, что язык развивается — есть и перспектива, и проверенная годами практика.
sergio_nsk Автор
02.04.2018 16:17Вот вышла краткая заметка о первоапрельском розыгрыше: Правда о "Указатели удаляют из C++".
Пять блогеров с разных уголков Земли договорились разыграть читателей в День дурака новостями об избавлении от указателей. Отклик на пять статей был гигантским, и растянулся от "давно пора!" до "это не может быть правдой!".
Kotauskas
04.04.2018 10:33-3Не верю. Что старый добрый C++ откажется от своей, возможно, главной особенности: производительности. Все эти shared_ptr и unique_ptr («эти» я пишу потому что я не любитель GC и сижу на C) просто в принципе не подходят для гейм-девелопмента. Никто не хочет 1 FPS в Counter-Strike: Global Offensive. Никто не хочет, чтобы огромную кодбазу на C++ переводили на C. Именно поэтому это просто утка…
Antervis
04.04.2018 11:40+2Все эти shared_ptr и unique_ptr просто в принципе не подходят для гейм-девелопмента.
unique_ptr ничуть не медленнее пары new/delete. Оверхед от shared_ptr в подавляющем большинстве случаев микроскопический в рамках приложения. Тем более что вы как сишник должны знать как часто в управлении временем жизни объектов на си используется тот же самый подсчет ссылок, что и внутри shared_ptrvladislavbelovdev
04.04.2018 15:30+1Согласен, в частности если каждый кадр не создаётся по туче
shared_ptr
(что было бы странно), а только используется, то разницу заметить сложно.
mayorovp
04.04.2018 13:55При чем тут вообще GC? shared_ptr и unique_ptr никакого отношения к сборщику мусора не имеют.
humbug
Несомненно, это будет удачным стечением обстоятельств, если комитету за 25 лет удастся проделать такую "титаническую" работу.
Я не понимаю, почему комитет не задеприкейтит создание новых проектов на этом языке в пользу Раста, у которого эти проблемы были решены 5 лет назад. Наконец-то подход комитета С++ потихоньку начинает понимать проблематику и то, как это стоило бы решать в нормальных условиях. Но он решает проблему дат и файловой системы.
gbg
Обещаете лично перевести на раст миллиарды строк легаси?
nexmean
А кроме огромной кодовой базы (читай легаси кода), есть хоть какой-то смысл использовать C++ вместо Rust?
ZaMaZaN4iK
А кроме следования веяниям моды, есть хоть какой-то смысл использовать Rust вместо C++?
khim
На самом деле, похоже, есть. В частности то, что указателей в смысле C++ нету — это плюсик. Язык молодой, необкатанный, но за ним уже пора следить…
Как в конце 80х все массово перешли с Паскаля на C (вы в курсе, что изначально и MacOS и Windows на Pascal были написаны?), так и тут может произойти через 30 лет…
pda0
Windows не была. И даже DOS не был. До версии 3.0 он был полностью написан на ассемблере. В 3.0 attrib.exe стал первой утилитой на C. Постепенно весь DOS был переписан на C. WinAPI 16 использовал соглашение вызовов __pascal ради экономии двух байт на стеке и того, что такой вызов был чуть быстрее. Что было важно для машин с десятками килобайт памяти и единицами мегагерц скорости.
Но свои версии компиляторов Pascal Microsoft делал до конца 80-х.
khim
То, что Windows была написана на Паскале легко понять, если немного думалку включить.
1. Компилятор Microsoft Pascal 1.10 — это 1981й год.
2. Первый компилятор C для IBM PC, Lattice C — это 1982й год.
3. Microsoft C 2.0 — это всё тот же самый Lattice C под другим брендом, только вышел он в 1984м.
Так на каком языке была написана Windows, если работа над ней началась в 1981м, а в 1983м безумный Стив Баллмер (которому пообещали, что «усё будет готово к 1983му и „наивный чукотский вьюноша“ поверил) устроил в Лас-Вегасе охренительную рекламу Windows (продукта, который не выйдет на рынок ещё два года)?
Другое дело, что до релиза эта версия (в отличие от MacOS) не добралась… это да — но изначально она писалась на смеси Assembler'а (без этого ни одна OS не обходится, вопрос лишь в пропорциях) и Pascal'я…
MacIn
Так первая Windows по вашему мнению была написана, или же был написан некий не увидевший свет концепт?
pda0
Windows 1.x как и ранние DOS была написана на ассемблере. Только с 2.0 появился код на C. В общем-то для начала 80-х это было нормой. Домашние пользователи могли писать хоть на бейсике, но те, кто поставлял им систему вынуждены были выжимать из компа всё.
nick758
Offtop: можно поподробнее про Windows на паскале? В Википедии про версию 1.01 сказано, что 85% C, остальное ассемблер. Больше ничего нагуглить не смог.
pda0
Этот миф ходит из-за того, что у WinAPI 16 было соглашение вызовов __pascal. Люди игнорируют что в начале 80-х это было самое популярное соглашение вызовов (причины написаны выше) и думают, что раз есть слово «паскаль», то и написано на нём было. А вот старый Mac OS, до десятки и правда на Pascal был.
nexmean
И это только то, что сразу на ум пришло.
VioletGiraffe
Забыли отвратительный синтаксис (ИМХО, конечно).
Fedcomp
Лучше чем у C++.
develop7
не «забыли», а «не взяли».
pda0
Ну, во первых, это всё равно недораст получается. И превратить C++ в Rust никаким напильником не выйдет. Хотя бы потому, что указатели далеко не единственная проблема.
А что касается легаси, то он никуда не денется. И принятие нового стандарта не превратит автоматически «8.5 миллионов строк C++ кода» хромиума в C++ код стандарта C++23.
alexeibs
Хромиум — неудачный пример. Код там вполне современный
pda0
Именно, что современный. Не C++23. Впрочем, похоже всё это оказалось качественным розыгрышем.
VioletGiraffe
Если вы считаете указатели проблемой — да, лучше пишите на Rust, С++ не для вас. Это не делает его плохим языком. Это всего лишь делает вас некомпетентным программистом на С++.
PsyHaSTe
В каждой статье про плюсы когда говорят про плюсы всегда появляются «Ненастоящие шотландцы», которые все делают неправильно. Плохой язык — тот, в котором легко допустить ошибку, которую легко могут предотвратить средства оптимизации, в данном случае — компилятор, хорошие — в котором это сделать сложно. От «правильного» или «неправильного» разработчика тут ничего не зависит, это свойство языка, а не конкретного человека.
Указатели мощная концепция, которая почти всегда не нужна, ибо ссылки практически все сценарии поддерживают лучше. Для оставшихся редких задач да, можно использовать указатели, и пометить соответствующие блоки типа «beware, here be dragons».
vladislavbelovdev
До тех пор, пока в Rust присутствует
unsafe
блок, комментарий про некомпетентных программистов является справедливым.PsyHaSTe
А можно определение «некометентности», пожалуйста? А то я полагаю, что у вас это «тот кто хоть раз в жизни делал double free и out of bounds access», подо что попадают все программисты планеты.
vladislavbelovdev
Ошибки в double free, out of bounds или делении на 0 вполне вероятны по невнимательности. Моя мысль в том, что пока в языке (любом) есть способ прострелить себе ногу (даже самый изощренный), люди будут это делать.
Я не согласен только с вашим определением «плохого языка», оно слишком категорично. Я не люблю называть языки, которые могут как-то приносить пользу, плохими. Возможно, я через чур оптимистичен.
PsyHaSTe
Мое мнение таково: если у нас есть равномощные (не в плане Тьюринг полноты, а в естественном смысле) языки, но в языке А способ прострелить себе ногу изощренный, а в Б — нет, то А лучше Б. Это собственно практическое применение принципа Паретто: если у нас есть множество альтернатив (в данном случае А и Б), и А не хуже Б по всем критериям, но лучше по хотя бы одному, то А — предпочтительная альтернатива.
vladislavbelovdev
Я согласен, что в данном случае А лучше Б, но Б не является плохим только по этому признаку.
Возможно, вы не правильно поняли меня про некомпетентность, я имел в виду не вас, а то, что всегда будут некомпетентные люди для любого языка, где есть такая возможность.
khim
You Can Write FORTRAN in any Language
Antervis
средний программист не вчера универ закончил, а полгода работы уже более чем достаточно научиться работать с памятью в современных плюсах. Вон в go, например, весь упор был на надежность, ради которой пожертвовали лаконичностью. Rust построен на принципе «явное лучше неявного», а я например считаю, что излишняя явность перегружает код второстепенными вещами — его проще писать, но сложнее читать. А читается код чаще.
awesomer
конечно научился, а то бы у него программы падали постоянно.
но есть такой фактор как невнимательность.
невозможно 100% времени быть 100% сконцентрированным.
и главное — зачем?
если можно это перепоручить компилятору.
Antervis
и что, программисты по невнимательности пишут new вместо make_shared?
Сконцентрированным быть всё равно придется, ибо большая часть ошибок — логические. Их зачастую куда дольше ловить и куда сложнее исправлять.
F0iL
В Хромиуме (точнее, в Блинке) умные указатели были еще до того, как они приобрели нынешний вид в современных стандартах C++.
А некоторое время назад они наоборот отказались от умных указателей в пользу сборщика мусора.
И да, кодовая база по-тихоньку, но рефакторится на C++11/C++14.
MacIn
А этого мало?
novikovag
Кресты и Раст два трупа, которых постоянно выкапывают и насилуют.
crea7or
В одном хромиуме 8.5 миллионов строк C++ кода.
struvv
Кстати firefox же работает на rust и c++ и работает он быстрее хрома, особенно на ресурсах кровавого интерпрайза
crea7or
А edge бывает и быстрее. И ресурсов не жрёт много и раста там нет.
crea7or
К тому же, раньше FF был на C++ и тормозил вообще безбожно. Им вон даже новый язык пришлось придумывать, чтобы заработало прилично. Так что это от программиста зависит, как оно работать будет.
PsyHaSTe
Если те же программисты перейдя на новый язык смогли написать FF, который перестал безбожно тормозить, то может это и есть показатель того, что смысл в расте есть?
crea7or
Для них — да и для тех кому нравится да.
PsyHaSTe
При чем тут нравится или нет? Это все равно, что купил монитор побольше или кресло поудобнее — и разработчик стал сразу эффективнее писать. Это вполне объективный показатель. Был разработчик на плюсах, имел такую-то эффективность. Ему дали раст, он стал писать лучше. Берем теперь кучу таких разработчиков, и получаем вполне себе адекватную метрику.
crea7or
Пост про C++ я не про раст — вот причём. В каждый пост про С++ приходят фанаты раста и начинают объяснять как «правильно» надо программировать.
PsyHaSTe
Это печально, но при чем тут это? Да приходят, но мы вроде другое обсуждали.
Eagle_NN
Скорее не так:
Была куча программистов на С++, которые тянули старый код годами.
Наняли новых (часть, конечно, переучили) и сделали глобальный рефакторинг.
И совсем не факт, что если бы наняли хороших архитекторов и потратили то-же время на рефакторинг получилось бы хуже.
Хром то, на C++ и не тормозит.
Tippy-Tip
Он перестал тормозить из-за того, что некоторый устаревший код не выполняется. Программа работает не в сферическом вакууме, а в многозадачных ОС, у которых есть оптимизаторы выполнения (к примеру, префетчер в Windows, в Linux это реализовано по-другому, но конечный результат тот же). Оптимизаторы выполнения работают в парадигме «Быстрая память – дефицитный ресурс для всех запущенных процессов», поэтому они и не загружают в ОЗУ те участки кода, которые никогда не будут выполняться (либо сбрасывают их на диск, чтобы освободить ОЗУ). И оптимизатору выполнения все равно на каком языке была написана программа, здесь в первую роль играет компилятор, а не язык. Поэтому выдавать ускорение быстродействия за преимущество, полученное из-за перехода на какой-либо новый язык программирования, мягко говоря, некорректно.
PsyHaSTe
Язык вполне может влиять на это. Никто же не сомневается, что наличие типов позволяет оптимизировать намного агрессивнее плюсовому компилятору, чем например JS-овскому? Если гооврить про плюсы, то такой гарантией может быть классический пример:
Из-за стандарта плюсы обязаны производить лишние операции в цикле, чтобы соблюсти правила алиасинга. Хотя передавать одну и ту же ссылку (или даже пересекающиеся) в src и dst это явно автор не предполагал. Но если поставить __restrict__, то основной кейз становится таким же быстрым, но теперь в случае нарушение гарантий (кто-то случайно не то передал) последствия могут быть намного хуже.
Собственно, тезис простой и думаю вы с ним согласны: чем сильнее система типов, тем больше простор действий для оптимизатора. Тут вот небольшая заметка в качестве примера, как это происходит по шагам. Можете описать, согласны ли вы с выводами?
FoxCanFly
Во всех вменяемых компиляторах включенная оптимизация дальше базовой по дефолту отключает эту проверку.
PsyHaSTe
Ни один оптимизатор не имеет права нарушать стандарт, это известно каждому. Никому не нужен быстрый некорректный код.
FoxCanFly
По стандарту нарушение aliasing — undefined behaviour, следовательно компилятор имеет право делать что угодно
humbug
А зачем вам быстрый некорректный код, когда существующая система типов в Раст позволяет вам написать такой же быстрый код, но при этом корректный? Что мешает лично вам?
FoxCanFly
Некорректный код пишет программист по своей глупости, и язык в этом не виноват. Если он не знает правил языка, на котором пишет — он профнепрегоден и при первом же таком косяке должен быть уволен по статье
PsyHaSTe
Видимо, команды таких проектов, как Chromium/FF/MySQL/Postgress/younameit надо давно разогнать, ибо в том же блоге PVS Studio каждую неделю выходит статья с целой пачкой найденых багов.
Ошибки совершают все, даже люди с 20-летним стажем. В любом языке. Но, может, лучше возложить часть нагрузки на язык, а не сваливать всю вину на программиста?
humbug
Всегда на такие "фразочки" отвечают: а покажите свой гитхаб. Более чем уверен, что если вы написали пару тысяч строк кода на С++, я найду в них багу. Ну-ка, товарищ, вперед!
mayorovp
Где именно в этом коде нарушение aliasing?
FoxCanFly
В этом коде его и нет, и его поведение defined не зависимо от того, перекрываются ли области по этим указателям или нет.
mayorovp
Именно так и есть. Поэтому оптимизатор ни с какими ключами не сможет ничего толком ускорить.
develop7
ссылку бы на godbolt, иллюстрирующую тезис
Tippy-Tip
Я приведу иллюстрацию к своему сообщению.
Есть программа SphericalCowCAD. В этой программе есть функции Foo(x) и Bar(y). Функция Foo вызывается в M*N раз чаще (M>>0, N>>0) функции Bar. Оптимизатор многозадачной ОС исключает (в соответствии с парадигмой дефицита быстрой памяти) загрузку функции Bar из медленной долговременной памяти в быструю память. Вопрос: на каком языке программирования написана программа SphericalCowCAD?
Cryvage
Несколько вопросов по коду.
1. Зачем вы передаёте указатель src, если потом не используете его?
2. Откуда взялся array? Это глобальная переменная?
3. Почему читаются значения из dest, когда по смыслу это место куда надо копировать, а не откуда?
Отсутствие проверки src и dest на null, и на равенство друг другу можно списать на то что это просто пример. Но в целом по коду вообще не понятно что он должен делать, и что вы хотите показать. Это выглядит как бессмыслица. Могу лишь предположить, что вы случайно запостили результат нескольких несогласованных между собой правок кода.
PsyHaSTe
Прошу простить, редактировал в последние секунды сообщение и не успел все поправить. Должно выглядеть это примерно так:
Antervis
а вы часто рефакторите код так, чтобы он стал хуже?
ukhegg
А это делали одни и те же программисты? не думаю, что вся команда бросила плюсы и переучилась на раст.
Да, в плюсах 1000 и 1 способ выстрелить себе в ногу, но в умелых руках и при должной осторожности можно делать действительно классные и быстрые вещи, например полноценный паттерн «состояние» на стеке
PsyHaSTe
Вполне допускаю, что делали одни и те же. В конце концов, авторы раста до того как появился раст писали скорее всего именно на плюсах, и именно на него ориентировались при его создании. И уж точно неоткуда было взяться растопрограммистам с опытом кроме как просто перевести кого-то из команды изнутри.
Насчет классных вещей — совсем не спорю. Есть языки, которые безопасны и там нельзя этого сделать — управляемые джавы и шарпы из таких. Есть плюсы где это можно сделать, но с безопасностью есть определенные проблемы. Раст на моей памяти первая удачная с моей точки зрения попытка усидеть на двух стульях. Более строгий анализатор с возможностью отключения проверок в некоторых местах (с явной аннотацией «я думаю тут все в порядке, но кто знает») мне кажется более продуктивен для разработчика, чем менее строгий. В конце концов всякие статические анализаторы для плюсов для того и придумали. Просто оказывается, что если запретить некоторые корректные, но сложноанализируемые вещи то анализатор становится намного полезнее. И пусть эти корректные вещи приходится либо переписывать так, чтобы уговорить компилятор пропустить их, либо воспользоваться unsafe. Но ведь во всем остальном проекте он будет помогать, а не мешать.
Я буквально на днях писал пример для интервью в одну компанию на расте. Писал часов 10, исправляя ошибки, в конце концов оно скомпилировалось. И это было бесподобно, потому что на моих ежедневных шарпах такого бы точно не произошло — NullRef где-нибудь или выход за границы массива — гарантированно. До этого у меня такое было всего один раз, когда я изучал хаскель. Там тоже происходит долгий диалог с анализатором, в конце которого получается рабочий продукт. Как по мне, это намного приятнее, чем сидеть с дебаггером.
buldo
Выход за границы на шарпе? Интересный вы код пишете, если не ходите по массиву, а вычисляется значения индексов на лету.
Ну и не помню когда вообще последний раз ловил npe.
А что это за тестовое, которое надо фигачить 10 часов? Можете в двух словах рассказать?
PsyHaSTe
IndexOutOfRange — действительно редкий гость, но иногда случается, особенно при работе со строками: string.Remove, string.Substring, вот это все.
Что касается NRE — просто с трудом могу поверить, что есть человек, который с ними редко сталкивается. Наряду с KeyNotFoundException это самые противные исключения, контекст которых абсолютно непонятен, и которые просто являются бичом.
Что касается тестового: там просто поиск на графе, просто исполнение осложнялось несколькими условиями. Во-первых я писал на языке, который начал изучать в конце прошлого года серьезно, когда IDE наконец начали нормально работать. Во-вторых я плохо знаком с алгоритмами на графах, и например я долго думал об алгоритме упаковки матрицы в вектор так, чтобы при ресайзе не нужно было ничего копировать поэлементно (вот мой вариант, с которым мне кстати еще и помогли, если есть идеи, как улучшить — welcome). Ну и в-третьих в задании просили писать production-ready код, поэтому сюда добавляется время на тесты, XML-доки и вот это все.
nelder
Быстрее? Тормозит безбожно. И теперь я понял почему.
alklimenko
Миллиарды строк легаси будут использовать new
humbug
Вы невнимательно прочли. Комитет должен рекомендовать начинать писать новые проекты на Раст, а не на С++. Тогда всем будет счастье.
gbg
Я рассуждал так — если комитет объявляет о закрытии c++ для всех новых проектов, следовательно, c++ тоже подлежит закрытию, как проект. Из чего следует, что легаси остается осиротевшим, из чего следует необходимость переноса легаси на раст.
humbug
Ну что вы. Легаси — важное наследие, которое необходимо поддерживать.
Выше высказали дельную мысль: новые фичи языка не превратят легаси в безопасный код, все равно останутся сырые указатели, утечки, UB и прочие вещи.
Поэтому одним из возможных важных этапов С++ было бы… делегирование своего продолжения в Rust, где уже все это пофикшено. Надеюсь, вы поняли мою мысль)
Antervis
фанаты раста в тредах про с++ как веганы на барбекю пикнике. Орут громче всех, а кто вас звал то?
humbug
Я умею и в С++, и в Раст. Так что имею право.
Antervis
я же, например, не ору в тредах про js что python лучше.
Zanak
Может быть потому, что ребята, которые пилят раст, сами решают, что станет стандартом в их языке, и делегировать это право комитету в их планы не входит?
Или вы предлагаете тупо списать? :)
humbug
Можно форкнуть язык комитетом, который будет сам решать, какие фичи будут переползать в Раст-форк. А что, хороший план)
Zanak
Питонисты пробовали на своем примере. Сколько их там сейчас, кроме общепризнанного CPython? Jython, IronPython, PyPy, RPython, это первое что гугл выдал. А большая часть народа все равно живет на CPython.