LINUX.ORG.RU

Ушат помоев в сторону крестолюбов

 , , ловите наркомана,


15

14

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

Последние 7 лет я пишу сугубо на C, и только под Linux (да, да -std=gnu99 и accept4, dup3, __attribute__((cleanup(dtor))) и прочие приятности, позволяющие сделать волосы шелковистее на 15.5%) и не понимаю, для чего вообще нужен C++? То, что на сишке делается красиво и элегантно, в крестах напоминает соитие парализованных дцпшников (к сожалению, утерял картинку, но именно этот образ всплывает в голове, когда вижу очередную порцию крестолапши).

Давайте посмотрим на типичного C++ разработчика: он использует STL, boost, многие любят Qt (не только для GUI), якобы чтобы «писать кроссплатформенный код». В итоге болезный не знает током ни WinAPI, ни POSIX — ничерта. Он абсолютно не разбирается, как работает целевая система, для которой пишет код! Крестокодер просто не осознает, какой лютый ужас кроется за его любимыми iostream-ами, какое лютое говно лежит в boost::filesystem::path, насколько убого-низкоуровневым является boost::asio в 2016 году.

Только крестораб может эпично обосраться и просадить производительность, забыв передавать по ссылке параметры для «горячих» функций (то есть, просто забыв написать «&» в нужном месте).

Также эти убогие завистливо смотрят на type inference в языках, проектировавшихся не как «C на стероидах», и в ответ начинают лепить template и auto не к месту, от чего код адово пухнет и даже IDE перестает его понимать.

Серьезно, просто прекратите писать на этом языке. В следующий раз, начиная новый проект, выберите java (щютка)/go/swift/rust/c. Прекратите насиловать труп и отравлять зловонием все вокруг!

Перемещено true_admin из talks

★★★★

Последнее исправление: a1batross (всего исправлений: 2)
Ответ на: комментарий от Miguel

Вначале - да. В конце - нет. Сборка мусора не прощает. Нужно будет большой такой кусок рефакторить добавляя пулы для всяких vec2 (фактически юзая new, delete руками).

Kuzy ★★★
()
Ответ на: комментарий от Kuzy

В принципе — соглашусь, что trade-off есть. Но насчёт «большой» — нет, вряд ли. Если бы это был большой кусок, то C++-код был бы испещрён delete-ами, а их как раз было не так, чтобы много.

Miguel ★★★★★
()
Ответ на: комментарий от kawaii_neko

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

#include <unordered_map>
#include <vector>
#include <utility>
#include <iostream>
#include <string>
template<class TKey, class TValue1, class TValue2>
class MyBMap
{
  typedef std::pair<TValue1, TValue2> DPair;
  typedef std::pair<TKey, DPair> TPair;
  std::vector<TPair> storage;
  int index;
  std::unordered_map<TKey, TPair*> key_map;
  std::unordered_map<TValue1, TPair*> value_map;

public:
  MyBMap() : index(0)
  {

  }
  void insert(TPair data)
  {
    storage.push_back(std::move(data));
    int oldIndex = index++;
    key_map.insert(std::make_pair(storage[oldIndex].first, &(storage[oldIndex])));
    value_map.insert(std::make_pair(storage[oldIndex].second.first, &(storage[oldIndex])));
  }

  TPair& search_by_first(const TKey& key)
  {
    auto it = key_map.find(key);

    if (it == key_map.end())
      throw std::exception("not found");

    return *it->second;
  }

  TPair& search_by_second(const TValue1& key)
  {
    auto it = value_map.find(key);

    if (it == value_map.end())
      throw std::exception("not found");

    return *it->second;
  }

};

Dudraug ★★★★★
()
Ответ на: комментарий от vertexua

Сретесь еще какой молоток имеет более правильную форму?

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

asaw ★★★★★
()
Ответ на: комментарий от Miguel

про трейдинг?

зависит от вида «трэйдинга» можно хоть на R, хоть на Python. У Окамла latency 10мс? А ести мне нужно например 3к/5k/7k транзакций в секунду ?

robotron5
()
Ответ на: комментарий от anonymous

3.14здобол, либо дурак.

+1, я не очень понимаю как можно получить O(1) без дополнительных индексирующих структур.

Dudraug ★★★★★
()

В следующий раз, начиная новый проект, выберите java (щютка)/go...

java (щютка)
go (не щютка)

Мы все тебя прекрасно поняли, продолжай держать нас в курсе.

znenyegvkby
()
Ответ на: комментарий от vertexua

Не, треды смысл имеют. Например напиши код для получения сегодняшнего дня недели в с++, а потом сравни с тем как это делается в с#/.net=)

Dudraug ★★★★★
()
Ответ на: комментарий от anonymous

Пока что не повзрослел уж до такой степени

vertexua ★★★★★
()
Ответ на: комментарий от anonymous

когда ты повзрослеешь ещё больше перестанешь в такие школотреды вообще писать.

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

asaw ★★★★★
()
Ответ на: комментарий от Dudraug

Тут по любому куча багов

К гадалке не ходи. К примеру, адрес TPair* при росте вектора изменится. Про число аллокаций лучше вообще не думать, emplace нет.

Сишка wins, я считаю.

P. S. Я понял: в кресты идут, кто трех строчек без сегфолта связать не может.

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

Этот код написан за 10 минут.

К примеру, адрес TPair* при росте вектора изменится.

Можно изначально выделить вектор побольше. В твоем коде на си я думаю увеличение числа бэкетов вообще не предусмотрена. Можно в std::set данные хранить вообще.

А вообще я б на твоем месте глянул таки на буст, я делаю ставку в 100%, что там все это уже реализовано и без багов.

Dudraug ★★★★★
()
Последнее исправление: Dudraug (всего исправлений: 1)
Ответ на: комментарий от Dudraug

В твоем коде на си я думаю увеличение числа бэкетов вообще не предусмотрена

Ты меня с лениным попутал. uthash — весьма взрослая штука. Она и растет, и уменьшается.

глянул таки на буст

Думаю, что я успею застать время, когда крестовики будут открещиваться от буста, как сейчас открещиваются от auto_ptr.

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от tailgunner

Этот персонаж не станет использовать Rust.

Как это? :-) Этот персонаж открыл тему, введение в которую заканчивается словами: «Серьезно, просто прекратите писать на этом языке. В следующий раз, начиная новый проект, выберите java (щютка)/go/swift/rust/c.» :-) Как видишь, Rust в списке рекомендаций есть :-)

anonymous
()
Ответ на: комментарий от kawaii_neko

Думаю, что я успею застать время, когда крестовики будут открещиваться от буста, как сейчас открещиваются от auto_ptr.

Думаю, они даже от unique_ptr<> будут открещиваться :-) Скажут, что unique_ptr<> с default_deleter ломает совместимость ABI :-)

anonymous
()
Ответ на: комментарий от RazrFalcon

RazrFalcon, если когда-нибудь пойдешь устраиваться на работу кодописателем, ни в коем случае не заикайся про хеш-таблицы и O(n). Когда речь идет об амортизированном времени поиска, вставки и удаления, в любой структуре данных претендующей на звание хеш таблицы, эти операции должны выполняться за O(const), что для удобства принято обозначать как O(1).

Плохой подбор хеш-функции, высокий load-factor — это все напчинается, когда vasyancpp садится за клавиатуру и начинает писать «кроссплатформенное ПО», не вникая в «незначительные детали имплементации».

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

Прекрасный образчик типичного C-шного кода от крестоненавистников. Копипаста, непереносимость, неосвобождение ресурсов, пренебрежение к ошибкам и закат солнца вручную.

Аналог на C++:

#include <cstring>
#include <chrono>
#include <string>
#include <memory>
#include <iostream>
#include <tuple>
#include <vector>

using namespace std;
using namespace chrono;

int main(int argc, char ** argv)
{
   if(4 != argc)
   {
      cout << "bench (c|m) len count" << endl;
      return 2;
   }

   const auto len = stoul(argv[2]);
   const auto count = stoul(argv[3]);

   vector<char> a(len, 0);
   vector<char> b(len, 0); 

   const auto bench = [count](auto fn, auto name) {
      const auto started_at = high_resolution_clock::now();
      for( unsigned long i = 0; i < count; ++i )
         fn();
      return make_tuple(
            duration_cast<nanoseconds>(high_resolution_clock::now() - started_at),
            name);
   };

   const auto r = ('c' == argv[1][0] ?
         bench([&]{ memcpy(&a[0], &b[0], len); }, "memcpy") :
         bench([&]{ memmove(&a[0], &b[0], len); }, "memmove"));

   cout << get<0>(r).count() / 1'000'000'000.0 << "s per " << get<1>(r) << endl;
   return 0;
}

eao197 ★★★★★
()
Ответ на: комментарий от andreyu

Типичный убогий крестокомментарий. Только для тебя и прямо сейчас происходит специальная олимпиада! Твой товарищ по крестовой команде поднатужился, изверг жиденький дурно пахнущий код Ушат помоев в сторону крестолюбов (комментарий) и, кажется, сошел с дистанции. Поможешь ли ты собрату по крестовому нейропараличу головного мозга или молча пройдешь мимо?

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

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

Dudraug ★★★★★
()
Ответ на: комментарий от eao197

Копипаста, непереносимость, неосвобождение ресурсов

Типичный крестовысер: auto на каждом шагу, lambda не к месту, tuple вместо структуры данных (согласен, прорыв после std::pair), убогое обращение с числами с плавающей точкой ну и само собой, надежда на всемогущий конпелятор, что тот превратит косвенный вызов в непосредственный.

Садись, двойка в четверть, родителей к директору на ковер!

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

в любой структуре данных претендующей на звание хеш таблицы, эти операции должны выполняться за O(const)

пздц! Да ты совсем тупой.

anonymous
()
Ответ на: комментарий от kawaii_neko

Про число аллокаций лучше вообще не думать, emplace нет.

Меняешь пуш бэки на эплейс и вектор на сэт. И проблемы уходят.

Dudraug ★★★★★
()
Ответ на: комментарий от RazrFalcon

Чтобы знать на чем написано не надо смотреть в сырцы. Достаточно посмотреть как функции именуются.

invy ★★★★★
()
Ответ на: комментарий от kawaii_neko

auto на каждом шагу, lambda не к месту, tuple вместо структуры данных

Сколько зависти. Но вы не расстраивайтесь, может быть со временем, в каком-нибудь -std=gnu2079 что-то похожее будет и в C.

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

Покажете компилятор С++14, который это не умеет?

eao197 ★★★★★
()
Ответ на: комментарий от kawaii_neko

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

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

andreyu ★★★★★
()
Ответ на: комментарий от eao197

Ну и самый сахарок:

$wc -l bench.cpp
40 bench.cpp
$ g++ -O2 -Wall -std=c++14 bench.cpp -o /dev/stdout | wc -c
14728
$ wc -l bench.c
35 bench.c
$ gcc -O2 -Wall /tmp/bench.c -o /dev/stdout | wc -c
8888
Победа по всем фронтам, ящитаю. :D

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

Садись, двойка в четверть, родителей к директору на ковер!

Уроки иди учи, сублиматор херов, обиженный родителями и директором :)

anonymous
()
Ответ на: комментарий от kawaii_neko

Победа по всем фронтам, ящитаю.

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

Ну и на целочисленное переполнение для 32-х битовых платформ проверьте. Так, на всякий случай. Ну, чтобы тема переносимости заиграла новыми красками.

А то решили удивить кого-то скоростью компиляции C++ного кода.

eao197 ★★★★★
()
Ответ на: комментарий от kawaii_neko
template<class TKey, class TValue1, class TValue2>
class MyBMap
{
  typedef std::pair<TValue1, TValue2> DPair;
  typedef std::pair<TKey, DPair> TPair;
  std::set<TPair> storage;

  std::unordered_map<TKey, TPair*> key_map;
  std::unordered_map<TValue1, TPair*> value_map;

public:
  MyBMap() = default;
  void insert(TPair data)
  {
    auto it = storage.emplace(std::move(data));
    if (!it.second)
      throw std::exception("not inserted");
    TKey k = it.first->first;
    TValue1 v1 = it.first->second.first;
    TPair& ref = (TPair&) *it.first;
    key_map.emplace(std::make_pair(std::move(k), &ref));
    value_map.emplace(std::make_pair(std::move(v1), &ref));
  }

  TPair& search_by_first(const TKey& key)
  {
    auto it = key_map.find(key);

    if (it == key_map.end())
      throw std::exception("not found");

    return *it->second;
  }

  TPair& search_by_second(const TValue1& key)
  {
    auto it = value_map.find(key);

    if (it == value_map.end())
      throw std::exception("not found");

    return *it->second;
  }

};

Вот тебе версия без инвалидации указателей и с эмплейсами.

Dudraug ★★★★★
()
Последнее исправление: Dudraug (всего исправлений: 2)

ТС - лайт версия Царя?

AIv ★★★★★
()
Ответ на: комментарий от eao197

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

В ход пошли крестоманевры.

удивить кого-то скоростью компиляции C++ного кода

Я про это даже не заикался. Считаю аморальным добивать лежащего.

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от Dudraug

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

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от vertexua

Так это как пример. В c#/.net прямо у строк есть методы ToUpper/ToLower. Есть методы StartsWith/EndsWith. У коллекций и строк есть метод Contains. std::find, std::string::find, std::map::find - ущербны, надеюсь не надо объяснять почему?

Dudraug ★★★★★
()
Ответ на: комментарий от Dudraug

Вот тебе версия без инвалидации указателей и с эмплейсами.

Ого, а если я не хочу для TValue2 operator< определять?

auto it = storage.emplace(std::move(data));

А если в TValue2 сложная структура со множеством полей? Ну, скажем, парочка std::string, пяток std::map? Я как-то сомневаюсь, что там без std::swap обойдется, который O(число-полей).

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от vertexua

Или может придут к идее модульной стандартной библиотеки или профилей.

ИМХО идея профилей лежит просто на поверхности, для меня загадка почему ещё не попытались её реализовать. Профили были бы полезны не только для стандартной библиотеки: можно было бы отключать опасные аспекты языка вроде выделения памяти и работы с голыми указателями - то, о чем говорил Страуструп представляя C++ Core Guidelines.

asaw ★★★★★
()
Ответ на: комментарий от kawaii_neko

Ого, а если я не хочу для TValue2 operator< определять?

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

Dudraug ★★★★★
()
Ответ на: комментарий от kawaii_neko

А если в TValue2 сложная структура со множеством полей? Ну, скажем, парочка std::string, пяток std::map? Я как-то сомневаюсь, что там без std::swap обойдется, который O(число-полей).

Ты что под роутеры пишешь? В прикладном софте на такое обычно пофиг, но а если вдруг внезапно лишние копирования/аллокации становятся узким местом, то тогда и начинай оптимизацию. Зачем превращать код в говно заранее из-за призрачного выигрыша по скорости работы/потреблению памяти?

Dudraug ★★★★★
()
Ответ на: комментарий от Dudraug

ты чо окуел?! На сишечке сразу пишется ровный и максимально быстрый код без багов, который в 100500 раз быстрее кода на крестах и во столько же раз читаемее. Пруфов не там, потому что это очевидно.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.