Две недели назад в Джэксонвилле встречался комитет стандарта ISO C++. Сегодня я хочу представить короткую сводку и написать о революционном решении, принятом на собрании в Джэксонвилле. Для получения дополнительной информации я рекомендую к прочтению статью C++ больше не будет иметь указатели. Комитет по стандартизации языка принял решение о том, что указатели будут объявлены устаревшими в C++20 и с большой долей вероятности будут удалены из C++23.


Откровенно говоря, то, что кажется революционном, — всего лишь последний шаг длинной эволюции.


image

Эволюция указателей в C++


Указатели существуют в C++ с самого начала. Мы получили их из C. С самого начала развития C++ всегда была тенденция сделать управление указателями более безопасным без значительных потерь.


В C++98 мы получили std::auto_ptr для выражения исключительного владения. Но std::auto_ptr имел большой изъян. Когда вы копирует std::auto_ptr, владение ресурсом передавалось копии. Копирование выглядело как перемещение. Изображение ниже показывает неприятное поведение std::auto_ptr.
image


Это было очень плохо, приводило к множеству серьёзных багов. Поэтому мы получили 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, счётчик ссылающихся указателей увеличивается. Посмотрите сюда:
image


Начиная с 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. Получаются такие числа:
image


Две вариации std::unique_ptr на Linux и Windows показывают такую же производительность, как обычные указатели. За деталями этого теста обратитесь к моей прошлой статье: Потребление памяти и производительность умных указателей.


Семантика владения


Честно говоря, мы используем указатели и, в частности, обычные указатели очень часто. Вопрос, должны ли вы использовать указатель, сводится к следующему: Кто владелец? К счастью, с помощью кода мы можем чётко выразить это.


  • Локальные объекты. Рантайм C++ как владелец автоматически управляет жизнью таких ресурсов. То же самое относится к глобальным объектам или членам класса. Справочники сводят это к области видимости.
  • Ссылки: я не владелец. Я только обеспечиваю, что ресурс не может быть пустым.
  • Обычные указатели: я не владелец. Я только ссылаюсь на ресурс, если он есть. Я не должен удалять ресурс.
  • std::unique_ptr: я исключительный владелец ресурса. Я могу явно освободить мой ресурс.
  • std::shared_ptr: я разделяю ресурс с другими std::shared_ptr. Я могу явно удалить мой разделяемый ресурс, если он больше никому не нужен.
  • std::weak_ptr: я не владелец ресурса, но я могу временно разделять ресурс при вызове моего метода std::weak_ptr::lock.

Нам нужно будет изменить только одну из шести практик использования указателей и мы рады следующему шагу в развитии C++.

Комментарии (134)


  1. humbug
    01.04.2018 13:51
    -2

    Несомненно, это будет удачным стечением обстоятельств, если комитету за 25 лет удастся проделать такую "титаническую" работу.


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


    1. gbg
      01.04.2018 14:17

      Обещаете лично перевести на раст миллиарды строк легаси?


      1. nexmean
        01.04.2018 15:48
        -15

        А кроме огромной кодовой базы (читай легаси кода), есть хоть какой-то смысл использовать C++ вместо Rust?


        1. ZaMaZaN4iK
          01.04.2018 16:07
          +24

          А кроме следования веяниям моды, есть хоть какой-то смысл использовать Rust вместо C++?


          1. khim
            01.04.2018 17:56
            +1

            На самом деле, похоже, есть. В частности то, что указателей в смысле C++ нету — это плюсик. Язык молодой, необкатанный, но за ним уже пора следить…

            Как в конце 80х все массово перешли с Паскаля на C (вы в курсе, что изначально и MacOS и Windows на Pascal были написаны?), так и тут может произойти через 30 лет…


            1. pda0
              01.04.2018 22:47
              +3

              MacOS и Windows на Pascal были написаны?


              Windows не была. И даже DOS не был. До версии 3.0 он был полностью написан на ассемблере. В 3.0 attrib.exe стал первой утилитой на C. Постепенно весь DOS был переписан на C. WinAPI 16 использовал соглашение вызовов __pascal ради экономии двух байт на стеке и того, что такой вызов был чуть быстрее. Что было важно для машин с десятками килобайт памяти и единицами мегагерц скорости.

              Но свои версии компиляторов Pascal Microsoft делал до конца 80-х.


              1. khim
                01.04.2018 23:28
                -6

                То, что 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'я…


                1. MacIn
                  02.04.2018 00:03
                  +1

                  Другое дело, что до релиза эта версия (в отличие от MacOS) не добралась… это да — но изначально она писалась на смеси Assembler'а (без этого ни одна OS не обходится, вопрос лишь в пропорциях) и Pascal'я…

                  Так первая Windows по вашему мнению была написана, или же был написан некий не увидевший свет концепт?


                1. pda0
                  02.04.2018 01:05

                  Windows 1.x как и ранние DOS была написана на ассемблере. Только с 2.0 появился код на C. В общем-то для начала 80-х это было нормой. Домашние пользователи могли писать хоть на бейсике, но те, кто поставлял им систему вынуждены были выжимать из компа всё.


            1. nick758
              02.04.2018 04:33

              Offtop: можно поподробнее про Windows на паскале? В Википедии про версию 1.01 сказано, что 85% C, остальное ассемблер. Больше ничего нагуглить не смог.


              1. pda0
                02.04.2018 14:34
                +1

                Этот миф ходит из-за того, что у WinAPI 16 было соглашение вызовов __pascal. Люди игнорируют что в начале 80-х это было самое популярное соглашение вызовов (причины написаны выше) и думают, что раз есть слово «паскаль», то и написано на нём было. А вот старый Mac OS, до десятки и правда на Pascal был.


          1. nexmean
            01.04.2018 18:26
            +3

            • Мощная система типов унаследованная от Haskell вместо ООП + аффинные типы и следующие из них статические гарантии(memory safety, fearless concurency, итп итд)
            • Модули
            • Стандартный пакетный менеджер вместо зоопарка несовместимых друг с другом решений
            • Стратегия развития языка(эпохи, RFC, вот это вот всё)
            • Синтаксис и стандартная библиотека без груза многолетней поддержки обратной совместимости
            • Синтаксическое разделение языка на safe и unsafe подмножества, которое позволяет легко определить где в коде используется чорная магия и прочее колдунство)

            И это только то, что сразу на ум пришло.


            1. VioletGiraffe
              02.04.2018 09:25

              Забыли отвратительный синтаксис (ИМХО, конечно).


              1. Fedcomp
                02.04.2018 11:25
                +1

                Лучше чем у C++.


              1. develop7
                02.04.2018 22:35

                не «забыли», а «не взяли».


          1. pda0
            01.04.2018 22:35
            +3

            Ну, во первых, это всё равно недораст получается. И превратить C++ в Rust никаким напильником не выйдет. Хотя бы потому, что указатели далеко не единственная проблема.

            А что касается легаси, то он никуда не денется. И принятие нового стандарта не превратит автоматически «8.5 миллионов строк C++ кода» хромиума в C++ код стандарта C++23.


            1. alexeibs
              02.04.2018 11:13

              Хромиум — неудачный пример. Код там вполне современный


              1. pda0
                02.04.2018 14:37

                Именно, что современный. Не C++23. Впрочем, похоже всё это оказалось качественным розыгрышем.


            1. VioletGiraffe
              02.04.2018 11:32

              Если вы считаете указатели проблемой — да, лучше пишите на Rust, С++ не для вас. Это не делает его плохим языком. Это всего лишь делает вас некомпетентным программистом на С++.


              1. PsyHaSTe
                02.04.2018 11:45

                В каждой статье про плюсы когда говорят про плюсы всегда появляются «Ненастоящие шотландцы», которые все делают неправильно. Плохой язык — тот, в котором легко допустить ошибку, которую легко могут предотвратить средства оптимизации, в данном случае — компилятор, хорошие — в котором это сделать сложно. От «правильного» или «неправильного» разработчика тут ничего не зависит, это свойство языка, а не конкретного человека.

                Указатели мощная концепция, которая почти всегда не нужна, ибо ссылки практически все сценарии поддерживают лучше. Для оставшихся редких задач да, можно использовать указатели, и пометить соответствующие блоки типа «beware, here be dragons».


                1. vladislavbelovdev
                  03.04.2018 16:54
                  -1

                  До тех пор, пока в Rust присутствует unsafe блок, комментарий про некомпетентных программистов является справедливым.


                  1. PsyHaSTe
                    03.04.2018 17:24
                    +2

                    А можно определение «некометентности», пожалуйста? А то я полагаю, что у вас это «тот кто хоть раз в жизни делал double free и out of bounds access», подо что попадают все программисты планеты.


                    1. vladislavbelovdev
                      03.04.2018 20:52
                      -1

                      Ошибки в double free, out of bounds или делении на 0 вполне вероятны по невнимательности. Моя мысль в том, что пока в языке (любом) есть способ прострелить себе ногу (даже самый изощренный), люди будут это делать.

                      Я не согласен только с вашим определением «плохого языка», оно слишком категорично. Я не люблю называть языки, которые могут как-то приносить пользу, плохими. Возможно, я через чур оптимистичен.


                      1. PsyHaSTe
                        03.04.2018 21:40

                        Мое мнение таково: если у нас есть равномощные (не в плане Тьюринг полноты, а в естественном смысле) языки, но в языке А способ прострелить себе ногу изощренный, а в Б — нет, то А лучше Б. Это собственно практическое применение принципа Паретто: если у нас есть множество альтернатив (в данном случае А и Б), и А не хуже Б по всем критериям, но лучше по хотя бы одному, то А — предпочтительная альтернатива.


                        1. vladislavbelovdev
                          04.04.2018 00:14

                          Я согласен, что в данном случае А лучше Б, но Б не является плохим только по этому признаку.

                          Возможно, вы не правильно поняли меня про некомпетентность, я имел в виду не вас, а то, что всегда будут некомпетентные люди для любого языка, где есть такая возможность.


                          1. khim
                            04.04.2018 10:29

                            You Can Write FORTRAN in any Language


                1. Antervis
                  03.04.2018 22:59
                  +1

                  средний программист не вчера универ закончил, а полгода работы уже более чем достаточно научиться работать с памятью в современных плюсах. Вон в go, например, весь упор был на надежность, ради которой пожертвовали лаконичностью. Rust построен на принципе «явное лучше неявного», а я например считаю, что излишняя явность перегружает код второстепенными вещами — его проще писать, но сложнее читать. А читается код чаще.


                  1. awesomer
                    04.04.2018 10:31
                    +2

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


                    конечно научился, а то бы у него программы падали постоянно.
                    но есть такой фактор как невнимательность.
                    невозможно 100% времени быть 100% сконцентрированным.

                    и главное — зачем?
                    если можно это перепоручить компилятору.


                    1. Antervis
                      04.04.2018 11:33

                      и что, программисты по невнимательности пишут new вместо make_shared?

                      Сконцентрированным быть всё равно придется, ибо большая часть ошибок — логические. Их зачастую куда дольше ловить и куда сложнее исправлять.


            1. F0iL
              02.04.2018 11:37

              В Хромиуме (точнее, в Блинке) умные указатели были еще до того, как они приобрели нынешний вид в современных стандартах C++.
              А некоторое время назад они наоборот отказались от умных указателей в пользу сборщика мусора.

              И да, кодовая база по-тихоньку, но рефакторится на C++11/C++14.


        1. MacIn
          01.04.2018 22:19
          +3

          А кроме огромной кодовой базы (читай легаси кода)

          А этого мало?


        1. novikovag
          02.04.2018 03:07
          -3

          Кресты и Раст два трупа, которых постоянно выкапывают и насилуют.


      1. crea7or
        01.04.2018 15:54

        В одном хромиуме 8.5 миллионов строк C++ кода.


        1. struvv
          01.04.2018 18:49

          Кстати firefox же работает на rust и c++ и работает он быстрее хрома, особенно на ресурсах кровавого интерпрайза


          1. crea7or
            01.04.2018 19:40
            +3

            А edge бывает и быстрее. И ресурсов не жрёт много и раста там нет.


          1. crea7or
            01.04.2018 19:47

            К тому же, раньше FF был на C++ и тормозил вообще безбожно. Им вон даже новый язык пришлось придумывать, чтобы заработало прилично. Так что это от программиста зависит, как оно работать будет.


            1. PsyHaSTe
              01.04.2018 19:57

              Если те же программисты перейдя на новый язык смогли написать FF, который перестал безбожно тормозить, то может это и есть показатель того, что смысл в расте есть?


              1. crea7or
                01.04.2018 20:05
                +1

                Для них — да и для тех кому нравится да.


                1. PsyHaSTe
                  01.04.2018 20:30

                  При чем тут нравится или нет? Это все равно, что купил монитор побольше или кресло поудобнее — и разработчик стал сразу эффективнее писать. Это вполне объективный показатель. Был разработчик на плюсах, имел такую-то эффективность. Ему дали раст, он стал писать лучше. Берем теперь кучу таких разработчиков, и получаем вполне себе адекватную метрику.


                  1. crea7or
                    01.04.2018 21:05
                    +4

                    Пост про C++ я не про раст — вот причём. В каждый пост про С++ приходят фанаты раста и начинают объяснять как «правильно» надо программировать.


                    1. PsyHaSTe
                      01.04.2018 22:30
                      -1

                      Это печально, но при чем тут это? Да приходят, но мы вроде другое обсуждали.


                  1. Eagle_NN
                    04.04.2018 10:32
                    +1

                    Скорее не так:
                    Была куча программистов на С++, которые тянули старый код годами.
                    Наняли новых (часть, конечно, переучили) и сделали глобальный рефакторинг.

                    И совсем не факт, что если бы наняли хороших архитекторов и потратили то-же время на рефакторинг получилось бы хуже.
                    Хром то, на C++ и не тормозит.


              1. Tippy-Tip
                02.04.2018 01:28

                Он перестал тормозить из-за того, что некоторый устаревший код не выполняется. Программа работает не в сферическом вакууме, а в многозадачных ОС, у которых есть оптимизаторы выполнения (к примеру, префетчер в Windows, в Linux это реализовано по-другому, но конечный результат тот же). Оптимизаторы выполнения работают в парадигме «Быстрая память – дефицитный ресурс для всех запущенных процессов», поэтому они и не загружают в ОЗУ те участки кода, которые никогда не будут выполняться (либо сбрасывают их на диск, чтобы освободить ОЗУ). И оптимизатору выполнения все равно на каком языке была написана программа, здесь в первую роль играет компилятор, а не язык. Поэтому выдавать ускорение быстродействия за преимущество, полученное из-за перехода на какой-либо новый язык программирования, мягко говоря, некорректно.


                1. PsyHaSTe
                  02.04.2018 11:38

                  Язык вполне может влиять на это. Никто же не сомневается, что наличие типов позволяет оптимизировать намного агрессивнее плюсовому компилятору, чем например JS-овскому? Если гооврить про плюсы, то такой гарантией может быть классический пример:

                  void copy(int* src, int* dest, int size) {
                      for(int i=0;i<size;++i) {
                          array[i] = dest[i];
                      }
                  }

                  Из-за стандарта плюсы обязаны производить лишние операции в цикле, чтобы соблюсти правила алиасинга. Хотя передавать одну и ту же ссылку (или даже пересекающиеся) в src и dst это явно автор не предполагал. Но если поставить __restrict__, то основной кейз становится таким же быстрым, но теперь в случае нарушение гарантий (кто-то случайно не то передал) последствия могут быть намного хуже.

                  Собственно, тезис простой и думаю вы с ним согласны: чем сильнее система типов, тем больше простор действий для оптимизатора. Тут вот небольшая заметка в качестве примера, как это происходит по шагам. Можете описать, согласны ли вы с выводами?


                  1. FoxCanFly
                    02.04.2018 12:20
                    -2

                    Во всех вменяемых компиляторах включенная оптимизация дальше базовой по дефолту отключает эту проверку.


                    1. PsyHaSTe
                      02.04.2018 12:45

                      Ни один оптимизатор не имеет права нарушать стандарт, это известно каждому. Никому не нужен быстрый некорректный код.


                      1. FoxCanFly
                        02.04.2018 13:06

                        По стандарту нарушение aliasing — undefined behaviour, следовательно компилятор имеет право делать что угодно


                        1. humbug
                          02.04.2018 13:09

                          А зачем вам быстрый некорректный код, когда существующая система типов в Раст позволяет вам написать такой же быстрый код, но при этом корректный? Что мешает лично вам?


                          1. FoxCanFly
                            02.04.2018 13:15

                            Некорректный код пишет программист по своей глупости, и язык в этом не виноват. Если он не знает правил языка, на котором пишет — он профнепрегоден и при первом же таком косяке должен быть уволен по статье


                            1. PsyHaSTe
                              02.04.2018 16:39
                              +1

                              Видимо, команды таких проектов, как Chromium/FF/MySQL/Postgress/younameit надо давно разогнать, ибо в том же блоге PVS Studio каждую неделю выходит статья с целой пачкой найденых багов.

                              Ошибки совершают все, даже люди с 20-летним стажем. В любом языке. Но, может, лучше возложить часть нагрузки на язык, а не сваливать всю вину на программиста?


                            1. humbug
                              02.04.2018 17:07

                              Всегда на такие "фразочки" отвечают: а покажите свой гитхаб. Более чем уверен, что если вы написали пару тысяч строк кода на С++, я найду в них багу. Ну-ка, товарищ, вперед!


                        1. mayorovp
                          02.04.2018 13:10

                          Где именно в этом коде нарушение aliasing?


                          1. FoxCanFly
                            02.04.2018 13:13

                            В этом коде его и нет, и его поведение defined не зависимо от того, перекрываются ли области по этим указателям или нет.


                            1. mayorovp
                              02.04.2018 13:17

                              Именно так и есть. Поэтому оптимизатор ни с какими ключами не сможет ничего толком ускорить.


                    1. develop7
                      02.04.2018 22:38

                      ссылку бы на godbolt, иллюстрирующую тезис


                  1. Tippy-Tip
                    03.04.2018 00:03

                    Я приведу иллюстрацию к своему сообщению.
                    Есть программа SphericalCowCAD. В этой программе есть функции Foo(x) и Bar(y). Функция Foo вызывается в M*N раз чаще (M>>0, N>>0) функции Bar. Оптимизатор многозадачной ОС исключает (в соответствии с парадигмой дефицита быстрой памяти) загрузку функции Bar из медленной долговременной памяти в быструю память. Вопрос: на каком языке программирования написана программа SphericalCowCAD?


                  1. Cryvage
                    03.04.2018 10:51

                    Несколько вопросов по коду.
                    1. Зачем вы передаёте указатель src, если потом не используете его?
                    2. Откуда взялся array? Это глобальная переменная?
                    3. Почему читаются значения из dest, когда по смыслу это место куда надо копировать, а не откуда?
                    Отсутствие проверки src и dest на null, и на равенство друг другу можно списать на то что это просто пример. Но в целом по коду вообще не понятно что он должен делать, и что вы хотите показать. Это выглядит как бессмыслица. Могу лишь предположить, что вы случайно запостили результат нескольких несогласованных между собой правок кода.


                    1. PsyHaSTe
                      03.04.2018 13:02
                      +2

                      Прошу простить, редактировал в последние секунды сообщение и не успел все поправить. Должно выглядеть это примерно так:

                      void copy(int* src, int* dest, int size) {
                          for(int i=0;i<size;++i) {
                              dest[i] = src[i];
                          }
                      }


              1. Antervis
                02.04.2018 09:55

                а вы часто рефакторите код так, чтобы он стал хуже?


              1. ukhegg
                02.04.2018 21:21

                А это делали одни и те же программисты? не думаю, что вся команда бросила плюсы и переучилась на раст.
                Да, в плюсах 1000 и 1 способ выстрелить себе в ногу, но в умелых руках и при должной осторожности можно делать действительно классные и быстрые вещи, например полноценный паттерн «состояние» на стеке


                1. PsyHaSTe
                  02.04.2018 22:29
                  +1

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

                  Насчет классных вещей — совсем не спорю. Есть языки, которые безопасны и там нельзя этого сделать — управляемые джавы и шарпы из таких. Есть плюсы где это можно сделать, но с безопасностью есть определенные проблемы. Раст на моей памяти первая удачная с моей точки зрения попытка усидеть на двух стульях. Более строгий анализатор с возможностью отключения проверок в некоторых местах (с явной аннотацией «я думаю тут все в порядке, но кто знает») мне кажется более продуктивен для разработчика, чем менее строгий. В конце концов всякие статические анализаторы для плюсов для того и придумали. Просто оказывается, что если запретить некоторые корректные, но сложноанализируемые вещи то анализатор становится намного полезнее. И пусть эти корректные вещи приходится либо переписывать так, чтобы уговорить компилятор пропустить их, либо воспользоваться unsafe. Но ведь во всем остальном проекте он будет помогать, а не мешать.

                  Я буквально на днях писал пример для интервью в одну компанию на расте. Писал часов 10, исправляя ошибки, в конце концов оно скомпилировалось. И это было бесподобно, потому что на моих ежедневных шарпах такого бы точно не произошло — NullRef где-нибудь или выход за границы массива — гарантированно. До этого у меня такое было всего один раз, когда я изучал хаскель. Там тоже происходит долгий диалог с анализатором, в конце которого получается рабочий продукт. Как по мне, это намного приятнее, чем сидеть с дебаггером.


                  1. buldo
                    03.04.2018 20:21

                    Выход за границы на шарпе? Интересный вы код пишете, если не ходите по массиву, а вычисляется значения индексов на лету.
                    Ну и не помню когда вообще последний раз ловил npe.
                    А что это за тестовое, которое надо фигачить 10 часов? Можете в двух словах рассказать?


                    1. PsyHaSTe
                      03.04.2018 21:35

                      IndexOutOfRange — действительно редкий гость, но иногда случается, особенно при работе со строками: string.Remove, string.Substring, вот это все.

                      Что касается NRE — просто с трудом могу поверить, что есть человек, который с ними редко сталкивается. Наряду с KeyNotFoundException это самые противные исключения, контекст которых абсолютно непонятен, и которые просто являются бичом.

                      Что касается тестового: там просто поиск на графе, просто исполнение осложнялось несколькими условиями. Во-первых я писал на языке, который начал изучать в конце прошлого года серьезно, когда IDE наконец начали нормально работать. Во-вторых я плохо знаком с алгоритмами на графах, и например я долго думал об алгоритме упаковки матрицы в вектор так, чтобы при ресайзе не нужно было ничего копировать поэлементно (вот мой вариант, с которым мне кстати еще и помогли, если есть идеи, как улучшить — welcome). Ну и в-третьих в задании просили писать production-ready код, поэтому сюда добавляется время на тесты, XML-доки и вот это все.


          1. nelder
            02.04.2018 04:33

            Быстрее? Тормозит безбожно. И теперь я понял почему.


      1. alklimenko
        01.04.2018 19:20
        +1

        Миллиарды строк легаси будут использовать new


      1. humbug
        01.04.2018 21:14

        Вы невнимательно прочли. Комитет должен рекомендовать начинать писать новые проекты на Раст, а не на С++. Тогда всем будет счастье.


        1. gbg
          01.04.2018 21:28

          Я рассуждал так — если комитет объявляет о закрытии c++ для всех новых проектов, следовательно, c++ тоже подлежит закрытию, как проект. Из чего следует, что легаси остается осиротевшим, из чего следует необходимость переноса легаси на раст.


          1. humbug
            02.04.2018 00:33

            Ну что вы. Легаси — важное наследие, которое необходимо поддерживать.


            Выше высказали дельную мысль: новые фичи языка не превратят легаси в безопасный код, все равно останутся сырые указатели, утечки, UB и прочие вещи.


            Поэтому одним из возможных важных этапов С++ было бы… делегирование своего продолжения в Rust, где уже все это пофикшено. Надеюсь, вы поняли мою мысль)


    1. Antervis
      02.04.2018 06:10
      +2

      фанаты раста в тредах про с++ как веганы на барбекю пикнике. Орут громче всех, а кто вас звал то?


      1. humbug
        02.04.2018 07:23

        Я умею и в С++, и в Раст. Так что имею право.


        1. Antervis
          02.04.2018 08:44
          +1

          я же, например, не ору в тредах про js что python лучше.


    1. Zanak
      02.04.2018 10:06

      Я не понимаю, почему комитет не задеприкейтит создание новых проектов на этом языке в пользу Раста

      Может быть потому, что ребята, которые пилят раст, сами решают, что станет стандартом в их языке, и делегировать это право комитету в их планы не входит?
      Или вы предлагаете тупо списать? :)


      1. humbug
        02.04.2018 13:07

        Можно форкнуть язык комитетом, который будет сам решать, какие фичи будут переползать в Раст-форк. А что, хороший план)


        1. Zanak
          02.04.2018 13:15

          Питонисты пробовали на своем примере. Сколько их там сейчас, кроме общепризнанного CPython? Jython, IronPython, PyPy, RPython, это первое что гугл выдал. А большая часть народа все равно живет на CPython.


  1. Anton3
    01.04.2018 14:05
    +2

    Прочитал заголовок, обрадовался, перечитал заголовок, посмотрел на дату, взгрустнул. Согласен с подходом Rust, когда указатели, конечно, не deprecated, но почти на все случаи жизни существуют ссылки и другие безопасные аналоги. Проблема недостатка безопасных аналогов как раз находится в процессе решения: string_view, span, observer_ptr.


    1. rz_hunTer
      01.04.2018 14:31
      -1

      Оригинал статьи-то вроде как от 26 марта…


    1. encyclopedist
      02.04.2018 11:33
      +1

      string_view и span не являются безопасными. Объект, на который они ссылаются, может быть удалён или перемещён, а вы и не заметите. Пример:


      std::string_view sv = function_returning_string();

      Тут string_view будет dangling, потому что ссылается на временную строку, которая сразу будет уничтожена.


  1. 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 договорились, вобще бы умора была.


    1. sergio_nsk Автор
      01.04.2018 14:39
      -1

      Да Вы, батенька, настоящий детектив!


    1. Fails
      01.04.2018 18:34

      Да, я сегодня утром тоже заметил) в тг-чат крестовый кидали оригинал английский )


    1. ukhegg
      02.04.2018 21:27

      западня для кроулеров?


  1. DistortNeo
    01.04.2018 14:45
    -1

    А если серьёзно, то C++ не хватает для умных указателей нормального синтаксиса.
    Зачем писать std::unique_ptr<T>, когда можно писать T^?
    Зачем писать std::make_unique<T>(...), когда можно писать new T^(...)?


    1. mayorovp
      01.04.2018 15:49
      +2

      А как вы будете обозначать shared_ptr? А weak_ptr? И еще какой-нибудь com_ptr, нестандартный но иногда очень нужный? Спецсимволов же не хватит…


      1. DistortNeo
        01.04.2018 17:13
        +1

        Достаточно краткой записи только для unique_ptr и shared_ptr. Редкоиспользуемые случаи же спецсимволами покрывать не нужно. Мне C++ очень нравится, но многословность несколько выбешивает.


        1. AllexIn
          01.04.2018 17:46
          +2

          Сделайте макрос, если очень хочется и не будет многословности.
          А лезть с синтаксическим сахаром в стандарт не нужно. Особенно с аргументацией «мне нравится unique_ptr, для его давайте схара, а остальные не надо, я ими не пользуюсь»


          1. Jamdaze
            02.04.2018 07:09

            Говориш не надо тебе сахара? Может и range based for тебе не надо?
            Только из за добавления сахара с++ стал юзабельным. С отвращением вспоминаю всё что было до с++03\с++11.
            Необходимость синтаксиса для «умных» указателей это следствие наличия в языке:
            а) Стандартного аллокатора, который по умолчанию используется для всего,
            б) Деструкторов — суть и соль языка,
            в) Собственно, необходимости работать с указателями.

            new должен возвращять умный указатель на объект или блок памяни (начало и конец), иначе мы не далеко уходим от голимого Си.


            1. gbg
              02.04.2018 08:25

              Который из умных указателей он должен возвращать? Самый нафаршированный, и потому медленный shred_ptr, или чего попроще?


            1. Antervis
              02.04.2018 08:43

              new — не такое часто используемое слово, чтобы экономия 10 знаков в сравнении с make_shared/make_unique была существенной. range based for нужен больше потому, что с ним ошибок меньше.


              1. Jamdaze
                04.04.2018 09:44

                Возможно вы меня не так поняли. У нас есть язык, и программирование на нём построено вокруг различных идиом в основе которых лежит использование деструкторов. В этом языке есть алакатор по умолчанию и есть оператор создания объекта, являющийся частью языка а не стандартной библиотеки.
                new — часть языка, и для того чтобы язык выглядел более самодостаточным, было бы логичным что new возвращяет безопасный указатель, с однозначным намёком что этот указатель надо будет освободить, после использования.


      1. 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();
        


    1. hdfan2
      01.04.2018 18:30
      +1

      Внезапно нечто подобное уже есть в Visual Studio.


      1. DistortNeo
        01.04.2018 21:56

        Да, это штука из Managed C++, а не из стандартного C++.


    1. FoxCanFly
      01.04.2018 19:13

      Если тащить все в синтаксис языка вместо реализации в библиотеках, через некоторое время язык превратится в свалку из странных синтаксических конструкций, но хватать их все равно не будет. А запомнить, какая из комбинаций знаков препинания создает shared_ptr, какая weak, а какая — вообще std::thread будет невозможно никому


      1. stychos
        03.04.2018 14:25
        -1

        Через некоторое время? Мне кажется, уже.


    1. abyrkov
      01.04.2018 20:28
      +1

      Может, перейдете на APL или J, на худой конец?


      1. Tangaroa
        03.04.2018 16:55

        на Lisp


    1. 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).


      1. DistortNeo
        01.04.2018 21:54
        +3

        в стандарте в некоторых случаях приходится явно разрешать неоднозначность интерпретации тех или иных конструкций

        Это следствие отсутствия ключевого слова "function".


        1. deviant_9
          01.04.2018 23:52

          В шаблонах даже без функций есть неоднозначности между объявлениями и выражениями — как, например, в случае a::b * c или a::b<c> d, где a — параметр шаблона.


  1. andy_p
    01.04.2018 14:54

    Первое апреля…


  1. laphroaig
    01.04.2018 15:31
    +20

    Еще к 23 году уберут постфиксную форму ++ ввиду ее неэффективности, а сам стандарт переименуют ++c23


  1. Wild__Recluse
    01.04.2018 15:31
    +3

    Как хорошо, что это шутка. У меня даже сердце остановилось.


    1. vazir
      01.04.2018 16:56
      +2

      Оригинал статьи от 26 марта… www.modernescpp.com/index.php/no-new-new


      1. daiver19
        01.04.2018 22:00
        +2

        И эта статья ссылается на статью от 1го апреля как на источник.


  1. valis
    01.04.2018 15:47

    И вас также с праздником :-)


  1. AWE64
    01.04.2018 16:10

    Сначала челюсть немного отвисла; потом вспомнил, какой сегодня день)


  1. TargetSan
    01.04.2018 17:02
    +2

    В каждой шутке есть доля шутки. Указатели позволяют слишком много. Ссылки обрезаны по самое небалуйся. reference_wrapper имеет почти нужную семантику, но, как ни смешно, слишком длинное имя. А optional из стандарта не имеет sentinel value оптимизации, из-за чего проигрывает голым указателям и по размеру, и по совместимости. К тому же слишком "легко" превращается в голое значение. В общем не хватает чего-то вроде optional<ref<T>>, имеющего почти нулевой оверхед по сравнению с указателем (за вычетом ассёртов в отладочном режиме).


    1. crea7or
      01.04.2018 17:36
      +1

      Возьмите c++ core guidelines и пишите в строгом соответствии с ними — никто же не мешает.


      1. TargetSan
        01.04.2018 17:48

        Если вы про owned/notnull — они дают какую-то семантику только в паре со статическим чекером, который их понимает. Последний раз такой чекер был только в Visual Studio. Т.е. его работоспособность даже в VS Build Tools под вопросом. В целом же, как я вижу, С++ всё больше требуется отдельный независимый от компилятора DSL для описания статических проверок :)


        1. Miron11
          01.04.2018 19:24

          Чего… Визуальная Студия все свои правила из библиотеки берёт. Но ассобенно сомневающиеся могут и саму Студию с командной строки запустить. В серьёзном проэкте всегда нужен свой статический анализ кода. У меня на проэкте гуру пишет базы для проэкта 25-й год. Она меня целует, за статический анализ. Когда глава фирмы прибегает и ждет, чтобы выдали новую процедуру такое пишут, что никаким опытом и знаниями волнение не защитить.


  1. crea7or
    01.04.2018 17:39
    +1

    C++ core guidelines: Resources management:


    1. TargetSan
      01.04.2018 17:49
      +3

      Это всё хорошо, но не описывает borrowed pointers и not-null pointers независимо от компилятора.


    1. DistortNeo
      01.04.2018 20:05
      +1

      Насчёт 11: предпочитаю всегда писать std::unique_ptr<T>(new T(...)), чем std::make_unique<T>(...). Причина простая: в первом случае работают подсказки IDE, во втором случае — нет.


  1. reversecode
    01.04.2018 19:42

    Если это не шутка, то совсем не понятно что означает «new removed»
    Удалить его вряд ли смогут, скорее всего пометят в рекомендации что использования new в коде, муветон, не более.
    А иначе не вижу что предлагается в замен, умные указатели это не то, они память тоже не с астрала черпают


  1. Tippy-Tip
    02.04.2018 01:05

    Я поверил статье пока не дошел до тэгов… :)
    AFAIK, тэги собирались удалять с Хабра (честно признаюсь: не ищу статьи по тэгам), но в данном случае тэги сыграли свою роль. Поэтому считаю что тэги на Хабре нужно оставить.
    P.S. С прошедшими Днём Архивов и Днём Дураков!


  1. geekmetwice
    02.04.2018 03:52
    -2

    Смех — смехом, но «развитие» С++ именно, что похоже на чью-то дебильную, 1-апрельскую шутку! Или же на известный квартет, меняющийся местами. Что бы в С++ ни ввели, безбожно уродливый синтаксис, вкупе с «совместимостью неуклюжей ООП модели», оставляет язык без шансов. Ну попрыгают ещё старпёры со своими «умными указателями», ещё пару сотен «списиалистов» выпустят ВУЗы, но язык так и останется «трупом страуса». Он просто ТУПИК.
    Комитет, вместо проедания денег, лучше бы взялся за D — вот уж кому не помешали бы деньги и дополнительные ресурсы! Ди решил множество проблем Сипипей, но комитет старых пердунов продолжает насиловать стюардессу, год от года становясь всё более смешным.


    1. Whuthering
      02.04.2018 08:59

      Выше уже были комментарии про растовцев:

      фанаты раста в тредах про с++ как веганы на барбекю пикнике. Орут громче всех, а кто вас звал то?

      В каждый пост про С++ приходят фанаты раста и начинают объяснять как «правильно» надо программировать.

      так вот, к фанатам D, как ни странно, то же самое полностью подходит :)


      1. guai
        02.04.2018 13:57

        Смех — смехом, а эта «первоапрельская» фича в D есть :P


    1. yurrig
      04.04.2018 10:33

      Соберите свой комитет по D, добейтесь авторитета в индустрии, народ к вам потянется, компиляторы напишет под ваш стандарт, компании начнут свой код на ваш D переносить. <<Тогда и поговорим>>


  1. JBMurloc
    02.04.2018 09:05

    Пошутили, блин. Давно такого дикого срача не видел в комментариях. Как же все напряглись-то.


  1. fukkit
    02.04.2018 09:46

    Кроме того, чтобы скомпилировать старую программу с помощью новых версий компилятора Microsoft без ошибок к сигнатуре каждой функции будет необходимо добавлять спецификатор "__unsafe_please_do_not_remove"


  1. VioletGiraffe
    02.04.2018 12:47

    Интересно, 55 плюсjв у статьи — это от тех, кто понял шутку, или от тех, кто не понял? :)


  1. guai
    02.04.2018 12:57

    Через год ждать анонса GC? :)


    1. deviant_9
      02.04.2018 21:10

      Опциональная поддержка GC (как я понимаю, без возможности вызова деструкторов) появилась ещё в C++11 (safely-derived pointers, std::declare_reachable и т. п.).


    1. 4e1
      03.04.2018 10:05

  1. asadullin_timur
    02.04.2018 13:10
    -1

    никто никуда переходить не будет :) если с++ станет удобнее, он только закрепит свои позиции популярного языка, тем более, что язык развивается — есть и перспектива, и проверенная годами практика.


  1. MazgutovRail
    02.04.2018 13:10

    Это очень жестоко.


  1. govage
    02.04.2018 16:01

    А зачем убирать указатели? Их же можно просто не использовать.


  1. sergio_nsk Автор
    02.04.2018 16:17

    Вот вышла краткая заметка о первоапрельском розыгрыше: Правда о "Указатели удаляют из C++".


    Пять блогеров с разных уголков Земли договорились разыграть читателей в День дурака новостями об избавлении от указателей. Отклик на пять статей был гигантским, и растянулся от "давно пора!" до "это не может быть правдой!".


  1. stychos
    03.04.2018 14:40

    Мощный троллинг, до конца статьи верил в написанное. Молодцы!


  1. Kotauskas
    04.04.2018 10:33
    -3

    Не верю. Что старый добрый C++ откажется от своей, возможно, главной особенности: производительности. Все эти shared_ptr и unique_ptr («эти» я пишу потому что я не любитель GC и сижу на C) просто в принципе не подходят для гейм-девелопмента. Никто не хочет 1 FPS в Counter-Strike: Global Offensive. Никто не хочет, чтобы огромную кодбазу на C++ переводили на C. Именно поэтому это просто утка…


    1. Antervis
      04.04.2018 11:40
      +2

      Все эти shared_ptr и unique_ptr просто в принципе не подходят для гейм-девелопмента.

      unique_ptr ничуть не медленнее пары new/delete. Оверхед от shared_ptr в подавляющем большинстве случаев микроскопический в рамках приложения. Тем более что вы как сишник должны знать как часто в управлении временем жизни объектов на си используется тот же самый подсчет ссылок, что и внутри shared_ptr


      1. vladislavbelovdev
        04.04.2018 15:30
        +1

        Согласен, в частности если каждый кадр не создаётся по туче shared_ptr (что было бы странно), а только используется, то разницу заметить сложно.


    1. mayorovp
      04.04.2018 13:55

      При чем тут вообще GC? shared_ptr и unique_ptr никакого отношения к сборщику мусора не имеют.