Кресты / Говнокод #27326 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
  91. 91
  92. 92
  93. 93
  94. 94
  95. 95
  96. 96
  97. 97
  98. 98
  99. 99
class MyString
{
public:
	MyString(const char* str)
	{
		symbol = strlen(str);
		this->str = new char[symbol + 1];
		for (int i = 0; i < symbol; i++)
		{
			this->str[i] = str[i];
		}
		this->str[symbol] = '\0';
	}
	int Size()
	{
		return symbol;
	}
	MyString()
	{
		str = nullptr;
		symbol = 0;
	}
	~MyString()
	{
		delete[] str;
	}
	MyString(const MyString& objct)
	{
		symbol = strlen(objct.str);
		this->str = new char[symbol + 1];
		for (int i = 0; i < symbol; i++)
		{
			this->str[i] = objct.str[i];
		}
		this->str[symbol] = '\0';
	}
	MyString operator ()(const char* objct)
	{
		if (this->str != nullptr)
		{
			delete[] this->str;
		}
		symbol = strlen(objct);
		this->str = new char[symbol + 1];
		for (int i = 0; i < symbol; i++)
		{
			this->str[i] = objct[i];
		}
		this->str[symbol] = '\0';
		return *this;
	}
	MyString& operator =(MyString& objct)
	{
		if (this->str != nullptr)
		{
			delete[] str;
		}
		symbol = strlen(objct.str);
		this->str = new char[symbol + 1];
		for (int i = 0; i < symbol; i++)
		{
			this->str[i] = objct.str[i];
		}
		this->str[symbol] = '\0';
		return *this;
	}
	MyString operator +(MyString& objct)//конкатенация строк
	{
		MyString NEWString;
		symbol = strlen(this->str);
		Ssymbol = strlen(objct.str);
		NEWString.str = new char[symbol + Ssymbol + 1];
		int i = 0;
		NEWString.symbol = symbol + Ssymbol;
		for (; i < symbol; i++)
		{
			NEWString.str[i] = this->str[i];
		}
		for (int j = 0; j < Ssymbol; j++, i++)
		{
			NEWString.str[i] = objct.str[j];
		}
		NEWString.str[symbol + Ssymbol] = '\0';
		return NEWString;
	}
	//перегруженные операторы........
 int main()
{
	MyString asd = "Go";
	MyString aa = "God";
	if (asd >= aa)
	{
		cout << "Первая переменная больше по символам чем вторая." << endl;
	}
	else
	{
		cout << "Первая переменная меньше по символам чем вторая." << endl;
	}
}

Свой класс строк. Что можно поправить для лучшей оптимизации?

Запостил: 1337 1337, (Updated )

Комментарии (78) RSS

  • Посмотри функции strcpy или memcpy. Некоторые циклы можно убрать.
    Ответить
  • MyString operator ()(const char* objct)


    А что это за метод? Ты портишь объект и возвращаешь его копию в конце.
    Ответить
  • Зря тут можно кинуть только 100 строк, кинул бы ESP для AC который юзает OpenGL

    З.Ы Я знаю что D3D будет лучше для написания ESP боксов и прочих читов, но просто решил упороться. А так с помощью D3D можно сделать обход OBS и прочих стриминговых программ. Правда для Shadow play такое не сработает, ибо она просто ВСЁ изображение с видяхи записывает, не отдельное окно.
    Ответить
  • > для лучшей оптимизации?
    #include <string>
    using MyString = std::basic_string<char>;

    Оптимизировала (как по строкам, так и по производительности).
    Ответить
  • Для начала стоит перестать течь в операторе присваивания при определённых случаях.
    Не течь а портить строку, простите. И вызывать UB.

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

    > class MyString
    Что это за класс? Зачем он нужен? Почему его нельзя заменить std::string? Почему его нельзя заменить классом-композитом с std::string? Почему его нельзя заменить классом-наследником std::string?
    Что делать, когда понадобится хранить строки из wchar_t?

    > this->str
    private:
        std::unique_ptr<char[]> str{};

    В C++ использовать сырые указатели для управления памятью — харам, запрет, анафема.

    > this->str = new char[symbol + 1];
    str = std::make_unique<char[]>(symbol + 1);



    > for (int i = 0; i < symbol; i++)
    std::memcpy

    > MyString(const char* str)
    Не хватает (если уж мы говорим про оптимизацию) ещё пары перегрузок:
    MyString(const char *str, size_t size)  // Конструктор с заданной длиной,
                                            // для оптимизации/поддержки строк с \0
    template<size_t TSize>
    MyString(const char (&str)[TSize])  // Конструктор из строкового литерала,
                                        // чтобы не считать длину в рантайме


    > int Size()
    size_t Size() const
    1. Размеры/индексы (за исключением случаев, когда возможны отрицательные числа) — только в size_t.
    2. Все методы, не изменяющие состояние объекта, следует помечать модификатором const,
    чтобы их можно было вызывать на константном объекте.

    > MyString()
    Примитивные инициализаторы членов класса лучше прописывать прямо в их объявлении (см. комментарий к this->str), это гарантирует, что они будут проинициализированы в любом случае.

    > ~MyString()
    После замены str на std::unique_ptr деструктор становится не нужен.

    > MyString(const MyString& objct)
    >> symbol = strlen(objct.str);
    symbol = objct.symbol
    Вычислять длину строки заново каждый раз не требуется — она уже вычислена в конструкторах.
    [Side note: почему objct? Мы же вроде как не в прошлом веке, нам, в отличие от создателей https://linux.die.net/man/2/creat, умещаться в пять символов не требуется]
    Ответить
    • > MyString operator ()(const char* objct)
      [Пропущено]

      > MyString& operator =(MyString& objct)
      const MyString& objct
      Ты не изменяешь второй объект, поэтому нужно принимать константную ссылку.

      > MyString operator +(MyString& objct)
      MyString operator +(const MyString& objct) const
      Оператор + не должен (если быть точным — от него не ожидается этого) изменять состояния ни текущего, ни второго объекта.
      >> symbol = strlen(this->str);
      Э, что? Так в MyString нет члена класса с длиной строки?!

      Наконец, если мы хотим иметь хоть какую-то производительность, то для этого класса совершенно обязательно реализовать move-семантику:
      1. Конструктор MyString(MyString && other);
      2. Оператор присваивания MyString & operator=(MyString && other);
      3. [Опционально] Метод Swap(MyString & other);
      4. [Опционально] Перегрузку std::swap(MyString & a, MyString & b);
      Полное объяснение move-семантики здесь в пару комментариев не уместится, поэтому по этому вопросу направлю в информационно-справочное бюро.
      Ответить
        • Пошли к нам в Coq, с dependent pattern matching поебёмся. Это даже геморнее, чем кресты.
          Ответить
        • Переходи лучше на Си - там всей этой хуйни нет.

          > C++ — довольно таки примитивное, но монстровое поделие, полное исторически сложившихся нелепых нагромождений. Человек, который хорошо в нем ориентируется — это хорошее зубрилко, а не хороший программист.
          Ответить
          • почему зубрилло противопоставляется хорошему программисту?
            Ответить
            • Очевидно, зубрилло это когда ты забиваешь себе мозг всякими языковыми говноньюансами, в которой нет никакогй логики или там математического смысла, когда это просто какое-то кривое ссаное говно, которое кто-то так придумал сделать таким просто потому что так захотелось. (например там типизации Хиндли-Милнера или теории категорий - там есть какое-то логическое математическое обоснвание, а почему в крестах какое-то там блядь наследования дерьма специализацией дерьма работает так а не иначе - это блядь просто так труп страуса придумал)

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

                А в Си говноньюансов на порядок меньше. Именно поэтому я за Си.
                Ответить
      • свап лучше делать первым. После этого операторы присваивания делаются лениво, поплёвывая в потолок.
        Ответить
      • > Оператор + не должен (если быть точным — от него не ожидается этого) изменять состояния ни текущего, ни второго объекта.

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

        Но вряд ли оверхед от создания новых экземпляров будет большой, да и с move-питушней не будет оверхеда от копирования.
        Ответить
        • как мув питущня связана с оператором +?
          Ответить
          • a = b + c;

            Без мува:
            Временный объект Т (b + c) скопируется в а (медленно).

            С мувом:
            Временный объект Т (b + c) мувнеца в а (быстро, но сложно).
            Ответить
            • "a" уже имеет какое-то значение что ли?
              тогда да
              Ответить
              • А если никакого не имеет, тогда что? Там же для такого кейса вроде бы свой тип инициализации, да?
                Ответить
                  • В C++ важно ня путать "=" и "=": первое — это оператор присваивания, который вызывает operator=(const T & other), а второе — это просто языковая конструкция-инициализация:
                    T a = b + c;  // Инициализация
                    a = b + c;  // Присваивание

                    Так вот в случае иняциализации в новых стандартах сработает mandatory copy elision (https://en.cppreference.com/w/cpp/language/copy_elision), и лишние копирование гарантированно ня вызовется.
                    Ответить
                    • А в старых нет?) В старых бы сначала создалось "a" (с каким значением?) а потом перезаписалось бы?

                      Это странно
                      Ответить
                      • В старых это было не обязательно. В них мог создаться временный объект (который вернул оператор+), затем a инициализировался копирующим конструктором из временной переменной. Затем временная переменная уничтожалась.
                        Ответить
                        • как же было написать в старых чтобы не по пидрски?

                          T a(b+ c) ?
                          Ответить
                          • Написать надо было разработчикам компилятора, если они ещё не сделали эту оптимизацию сами.

                            В этом варианте тоже а+b могло бы создать временную переменную, которая использовалась бы в копирующем конструкторе.
                            Ответить
                            • Какой пиздец) А если у меня конструктор тяжелый? И деструктор?
                              Как вообще люди писали на С++ двадцать лет назад?

                              Спец. фабричный метод делали?
                              Ответить
                                  • В крестах редко иммутабельные типы делают. const въеби да и всё, если хочешь чтобы значение не менялось.
                                    Ответить
                                    • Точно) У меня от помоечных япов без const в голове малость насрано, и я всё время забываю, что ператор += может быть и не const, а все остальные, ничего не меняющие методы, const
                                      Ответить
        • Нят, мутабельный оператор + — это крайне неинтуитивная подлянка, примерно как постфиксный operator++, возвращающий уже изменённый объект; яндере-тян, читающая такой код, будет очень огорчена.

          Для производительности обычно каждый operatorX реализуют через соответствующий operatorX=, примерно так:
          T & operator+=(const T & other)
          {
              // ...тяжёлые операции, модифицирующие this...
              return *this;
          }
          
          T operator+(const T & other) const
          {
              T temp(*this);
              temp += other;
              return temp;  // Нядеемся на NRVO
          }

          Тогда кому нядо производительность — тот сам будет заводить буфера и вызывать +=.
          Ответить
          • А чем плох мувающий плюс? Куски временных объектов сможет реюзать да и случайно его не вызвать.

            Для списков каких-нибудь вообще норм, имхо.
            Ответить
            • Не мувающий, а мутабельный. Мувающий вроде такого:
              T operator+(T && other) const {
                  T temp(std::move(other));
                  temp += *this;  // Если + симметричный
                  return temp;
              }

              — как раз нормально. А мутабельный — это примерно так:
              T & operator+(const T & other) {
                  this->something += other.something;
                  return *this;
              }
              Ответить
              • Это же отличный способ заставить пользователя твоей либы почитать документацию! Потом из неё он узнает, что операторы || и && тоже перегружены и писать ( (x = myObjectFactory.create()) || KillAllHumans() ) не стоило. Выяснит, что std::addressof существует не зря и нужно использовать его а не перегруженный &. Жаль, тернарники нельзя перегружать и запятую починили.
                Ответить
                • Amateurs! В Coq можно переопределить пробелы, скобки и чёрта лысого.
                  Ответить
                      • Офигенно. А если джве нотации подходят к одному и тому же коду, то будет ошибка?
                        Ответить
                        • Не обязательно, парсер сначала по приоритетам попытается разрулить.
                          Ответить
                          • Infix "(" := eq (at level 10).
                            
                            Check ( 1 ( 2). (* работает как надо *)
                            Ответить
                    • Для нотаций там есть scopes, а функции из модулей не обязательно явно импортировать:

                      Infix "(" := eq (at level 10, only parsing) : foo.
                      Delimit Scope foo with foo.
                      Open Scope foo. (* let the madness begin *)
                      Check ( 1 ( 2).
                      
                      Require MyModule.
                      Module M := MyModule.
                      
                      M.pitooshnya.
                      Ответить
    • > Что это за класс? Зачем он нужен?
      NIH

      > Почему его нельзя заменить std::string?
      NIH

      > Почему его нельзя заменить классом-композитом с std::string?
      NIH

      > Почему его нельзя заменить классом-наследником std::string?
      NIH

      > Что делать, когда понадобится хранить строки из wchar_t?
      Страдать Изобретать ещё один класс. Job Security
      Ответить
      • Что это такое?
        (Хуй! Хуй! Хуй!)
        Что тебе приснилось?
        (Хуй! Хуй! Хуй!)
        Как тебе живётся
        (Хуй! Хуй! Хуй!)
        Вместе с яйцами?
        В облаках летает!
        (Хуй! Хуй! Хуй!)
        Ласточек пугает!
        (Хуй! Хуй! Хуй!)
        Как тебе живётся
        (Хуй! Хуй! Хуй!)
        Между двух яйиц?

        https://youtu.be/pCnKChDwh1M
        Ответить
  • кастомный класс, прибитый гвоздём к char, не нужен
    Ответить
    • Да, там не было защиты от создания строки "nigger" и её отменили.
      Ответить

Добавить комментарий

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8