Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
Зря тут можно кинуть только 100 строк, кинул бы ESP для AC который юзает OpenGL
З.Ы Я знаю что D3D будет лучше для написания ESP боксов и прочих читов, но просто решил упороться. А так с помощью D3D можно сделать обход OBS и прочих стриминговых программ. Правда для Shadow play такое не сработает, ибо она просто ВСЁ изображение с видяхи записывает, не отдельное окно.
Открой заголовочный файл iostream.
Из него перейди к заголовочному файлу istream.
Из него перейди к заголовочному файлу ostream.
Из него перейди к заголовочному файлу xlocnum.
Из него перейди к заголовочному файлу streambuf.
Из него перейди к заголовочному файлу xiosbase.
Из него перейди к заголовочному файлу xlocale.
Из него перейди к заголовочному файлу xlocinfo.
Из него перейди к заголовочному файлу xstring.
В нём перейди к строке 2279. Там на твоём компиляторе и будет определение std::basic_string. Тебе повезло.
> 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 =(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-семантики здесь в пару комментариев не уместится, поэтому по этому вопросу направлю в информационно-справочное бюро.
> C++ — довольно таки примитивное, но монстровое поделие, полное исторически сложившихся нелепых нагромождений. Человек, который хорошо в нем ориентируется — это хорошее зубрилко, а не хороший программист.
Очевидно, зубрилло это когда ты забиваешь себе мозг всякими языковыми говноньюансами, в которой нет никакогй логики или там математического смысла, когда это просто какое-то кривое ссаное говно, которое кто-то так придумал сделать таким просто потому что так захотелось. (например там типизации Хиндли-Милнера или теории категорий - там есть какое-то логическое математическое обоснвание, а почему в крестах какое-то там блядь наследования дерьма специализацией дерьма работает так а не иначе - это блядь просто так труп страуса придумал)
А хороший программист не ебется с говноньюансами ублюдски-кривого языка, а решает прикладные задачи, т.е. голова у него забита не говноправилами говноязыка что вот это так наследуется, это так не наследуется, а вот эта говноспециализация хуйни через хуйню вот так работает, а решением прикладной задачи.
И получается так, что с таким говнязыками ты решаешь не прикладную задачу, а ебешь себе мозг говноньюансами говнгоязыка, в которых ничего красивого или элегантного нет. И вот это хуево.
А в Си говноньюансов на порядок меньше. Именно поэтому я за Си.
> Оператор + не должен (если быть точным — от него не ожидается этого) изменять состояния ни текущего, ни второго объекта.
Это если объект малепусенький, а если он большой и инициализация у него долгая, то лучше, вероятно, перезаписывать его. Но выглядеть будет плохо, да, тогда уж лучше оператор += переопределять.
Но вряд ли оверхед от создания новых экземпляров будет большой, да и с move-питушней не будет оверхеда от копирования.
Насколько я понял, если у тебя нет мове-конструктора, то даже в пустое А у тебя произведется копирование, будет дикий оверхед и проц сгорит, поэтому всегда надо делать мове-семантику.
В C++ важно ня путать "=" и "=": первое — это оператор присваивания, который вызывает operator=(const T & other), а второе — это просто языковая конструкция-инициализация:
T a = b + c; // Инициализация
a = b + c; // Присваивание
В старых это было не обязательно. В них мог создаться временный объект (который вернул оператор+), затем a инициализировался копирующим конструктором из временной переменной. Затем временная переменная уничтожалась.
Точно) У меня от помоечных япов без 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
}
Тогда кому нядо производительность — тот сам будет заводить буфера и вызывать +=.
Это же отличный способ заставить пользователя твоей либы почитать документацию! Потом из неё он узнает, что операторы || и && тоже перегружены и писать ( (x = myObjectFactory.create()) || KillAllHumans() ) не стоило. Выяснит, что std::addressof существует не зря и нужно использовать его а не перегруженный &. Жаль, тернарники нельзя перегружать и запятую починили.
Что это такое?
(Хуй! Хуй! Хуй!)
Что тебе приснилось?
(Хуй! Хуй! Хуй!)
Как тебе живётся
(Хуй! Хуй! Хуй!)
Вместе с яйцами?
В облаках летает!
(Хуй! Хуй! Хуй!)
Ласточек пугает!
(Хуй! Хуй! Хуй!)
Как тебе живётся
(Хуй! Хуй! Хуй!)
Между двух яйиц?
А что это за метод? Ты портишь объект и возвращаешь его копию в конце.
З.Ы Я знаю что D3D будет лучше для написания ESP боксов и прочих читов, но просто решил упороться. А так с помощью D3D можно сделать обход OBS и прочих стриминговых программ. Правда для Shadow play такое не сработает, ибо она просто ВСЁ изображение с видяхи записывает, не отдельное окно.
Оптимизировала (как по строкам, так и по производительности).
У меня всё прекрасно компилируется.
#include <Windows.h>
#include "Array.h"
#pragma warning (disable : 26495)
Array.h:
#pragma once
#include <iostream>
#pragma warning (disable : 4244)
#pragma warning (disable : 4083)
using namespace std;
Стандарт ISO C++ 17.
IDE VS 2019
Из него перейди к заголовочному файлу istream.
Из него перейди к заголовочному файлу ostream.
Из него перейди к заголовочному файлу xlocnum.
Из него перейди к заголовочному файлу streambuf.
Из него перейди к заголовочному файлу xiosbase.
Из него перейди к заголовочному файлу xlocale.
Из него перейди к заголовочному файлу xlocinfo.
Из него перейди к заголовочному файлу xstring.
В нём перейди к строке 2279. Там на твоём компиляторе и будет определение std::basic_string. Тебе повезло.
По ня ла.
Не течь а портить строку, простите. И вызывать UB.
И сделать аргумент константным тоже неплохо было бы.
> class MyString
Что это за класс? Зачем он нужен? Почему его нельзя заменить std::string? Почему его нельзя заменить классом-композитом с std::string? Почему его нельзя заменить классом-наследником std::string?
Что делать, когда понадобится хранить строки из wchar_t?
> this->str
В C++ использовать сырые указатели для управления памятью — харам, запрет, анафема.
> this->str = new char[symbol + 1];
> for (int i = 0; i < symbol; i++)
std::memcpy
> MyString(const char* str)
Не хватает (если уж мы говорим про оптимизацию) ещё пары перегрузок:
> 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 =(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-семантики здесь в пару комментариев не уместится, поэтому по этому вопросу направлю в информационно-справочное бюро.
> C++ — довольно таки примитивное, но монстровое поделие, полное исторически сложившихся нелепых нагромождений. Человек, который хорошо в нем ориентируется — это хорошее зубрилко, а не хороший программист.
А хороший программист не ебется с говноньюансами ублюдски-кривого языка, а решает прикладные задачи, т.е. голова у него забита не говноправилами говноязыка что вот это так наследуется, это так не наследуется, а вот эта говноспециализация хуйни через хуйню вот так работает, а решением прикладной задачи.
А в Си говноньюансов на порядок меньше. Именно поэтому я за Си.
Это если объект малепусенький, а если он большой и инициализация у него долгая, то лучше, вероятно, перезаписывать его. Но выглядеть будет плохо, да, тогда уж лучше оператор += переопределять.
Но вряд ли оверхед от создания новых экземпляров будет большой, да и с move-питушней не будет оверхеда от копирования.
Без мува:
Временный объект Т (b + c) скопируется в а (медленно).
С мувом:
Временный объект Т (b + c) мувнеца в а (быстро, но сложно).
тогда да
Насколько я понял, если у тебя нет мове-конструктора, то даже в пустое А у тебя произведется копирование, будет дикий оверхед и проц сгорит, поэтому всегда надо делать мове-семантику.
Так вот в случае иняциализации в новых стандартах сработает mandatory copy elision (https://en.cppreference.com/w/cpp/language/copy_elision), и лишние копирование гарантированно ня вызовется.
Это странно
T a(b+ c) ?
В этом варианте тоже а+b могло бы создать временную переменную, которая использовалась бы в копирующем конструкторе.
Как вообще люди писали на С++ двадцать лет назад?
Спец. фабричный метод делали?
Для производительности обычно каждый operatorX реализуют через соответствующий operatorX=, примерно так:
Тогда кому нядо производительность — тот сам будет заводить буфера и вызывать +=.
Для списков каких-нибудь вообще норм, имхо.
— как раз нормально. А мутабельный — это примерно так:
NIH
> Почему его нельзя заменить std::string?
NIH
> Почему его нельзя заменить классом-композитом с std::string?
NIH
> Почему его нельзя заменить классом-наследником std::string?
NIH
> Что делать, когда понадобится хранить строки из wchar_t?
Страдать Изобретать ещё один класс. Job Security
(Хуй! Хуй! Хуй!)
Что тебе приснилось?
(Хуй! Хуй! Хуй!)
Как тебе живётся
(Хуй! Хуй! Хуй!)
Вместе с яйцами?
В облаках летает!
(Хуй! Хуй! Хуй!)
Ласточек пугает!
(Хуй! Хуй! Хуй!)
Как тебе живётся
(Хуй! Хуй! Хуй!)
Между двух яйиц?
https://youtu.be/pCnKChDwh1M