Здравствуйте, Shmj, Вы писали:
S>Немножко было времени на выходных и по вечерам — почитал учебник Rust. И придумал для таких же как я простой и наглядный пример, который демонстрирует суть владения — зачем оно вообще нужно и в чем смысл. Вот пример:
S>
Немножко было времени на выходных и по вечерам — почитал учебник Rust. И придумал для таких же как я простой и наглядный пример, который демонстрирует суть владения — зачем оно вообще нужно и в чем смысл. Вот пример:
#include <iostream>
struct Class1 { const int i1 = 42; };
void fun1(std::unique_ptr<Class1> smart_ptr){}
int main()
{
auto smart_ptr1 = std::make_unique<Class1>();
fun1(std::move(smart_ptr1));
std::cout << smart_ptr1->i1 << std::endl;
}
Компилятор С++ это принимает и не пикнет — максимум варнинг выдаст, и то не всегда. А ведь это 100% ошибка без вариантов. А в Rust право владения — суть концепция самого языка.
Почему я начал почитывать Rust? Один чел. сказал что разобравшись с Rust — лучше начинаешь понимать другие языки, в частности тот же C++. Ведь в С++ умные указатели ведь тоже завязаны на владение, однако нет парадигмы в самом языке, которая способна выявлять подобные ошибки.
По сути Rust — это просто более строгий язык, который ошибки заменит на этапе компиляции. Примерно как если сравнить C++ и Python — так можно сравнить Rust и C++ — первый более строгий, второй менее.
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, Shmj, Вы писали:
S>>придумал для таких же как я простой и наглядный пример... CC>
CC>Твой наглядный пример:
Кулхацкеры из 9Б так НИКОГДА не ошибаются, верно? Так только анскиллы из 8А делают?
Доля правды тут только в том что зачастую дешевле ошибиться, подорваться и исправить, чем часами ублажать компилятор. Хотя и не везде.
Если же человек говорит что всегда 100% внимателен и никогда не допускает ошибок на внимательность — то с ним всерьёз можно не разговаривать, над ним можно тупо ржать.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
S>Вроде очевидно, что тип с префикосм "unique" не должен так использоваться
Да ладно вам. Накинулись на человека. Как раз здесь Шмыж, как ни странно, прав.
Не редко бывают случаи, когда кто-то создает объект, а затем передает ответственность за этот объект кому-то еще. Как раз с помощью std::unique_ptr. Что-то вроде:
void ensure_valid(const Transaction & trx);
void log_acceptance(const Transaction & trx);
void push_to_processing(std::unique_ptr<Transaction> trx);
...
while(!stop) {
std::unique_ptr<Transaction> trx = acquire_new_trx();
ensure_valid(*trx); // Не отдаем владение.
log_acceptance(*trx); // Не отдаем владение.
push_to_processing(std::move(trx)); // Отдали владение и забыли про объект.
}
Так что наличие std::unique_ptr<T> как аргумент по значению однозначно указывает на то, что вызываемая функция забирает и объект, и ответственность за его дальнейшую судьбу себе.
Здравствуйте, Michael7, Вы писали:
M>А теперь напиши связный список на rust
Я тоже читал эту статью с Хабра и она меня ввела в заблуждение. Я думал что это реально сложно или какие-то проблемы с этим. На самом деле автор не до конца разобрался а уже попытался выдать перл.
С непривычки кажется что это сложно. На самом деле вам нужно знать всего 2 вещи:
1. Если может не быть значения — используем Option.
2. Умные указатели целиком аналогично С++, только есть проверка перемещения. Box — это полный аналог unique_ptr.
// Определение структуры узла спискаstruct Node<T> {
value: T,
next: Option<Box<Node<T>>>,
}
// Определение структуры спискаpub struct LinkedList<T> {
head: Option<Box<Node<T>>>,
}
impl<T> LinkedList<T> {
// Создать новый пустой списокpub fn new() -> Self {
LinkedList { head: None }
}
// Добавить элемент в начало спискаpub fn push(&mut self, value: T) {
let new_node = Box::new(Node {
value,
next: self.head.take(),
});
self.head = Some(new_node);
}
// Удалить и вернуть первый элемент списка, если он естьpub fn pop(&mut self) -> Option<T> {
self.head.take().map(|node| {
self.head = node.next;
node.value
})
}
// Проверить, пуст ли списокpub fn is_empty(&self) -> bool {
self.head.is_none()
}
}
fn main() {
let mut list = LinkedList::new();
list.push(1);
list.push(2);
list.push(3);
while !list.is_empty() {
println!("{}", list.pop().unwrap());
}
}
Здравствуйте, DiPaolo, Вы писали:
DP>Все просто: не нравится — не пиши! Херли ныть ходить
Так если популярность языка затащит на него очередные 100500 индусов которые напишут херню и от этого, например, тебя убьёт взбунтовавшимся автомобилем?
Если бы это было частным проектом, "не нравится — не пиши" было бы адекватно. А так — чем больше обсуждений с вытаскиванием проблем, тем лучше.
В идеале бы ещё, конечно, демонстрации и пикеты перед зданием ISO "Прекратить херню!", но на это программистов не сподвигнуть, делаем что в силах.
Здравствуйте, klopodav, Вы писали:
DP>>>Все просто: не нравится — не пиши! Херли ныть ходить
N>>Так если популярность языка затащит на него очередные 100500 индусов которые напишут херню и от этого, например, тебя убьёт взбунтовавшимся автомобилем?
K>Эти проблемы касаются в первую очередь не языка, а других вещей — технологии конструирования автомобилей, тестирования и т.п.
В языке где undefined behavior может взорваться где угодно в зависимости от изменений за миллион строк от него — никакое тестирование и никакие правила конструирования не помогут против таких диверсий. Просто они чуть-чуть реже будут ломать работу.
То же самое в языке, где если 99.99% кода написано с использованием всех правил контроля за памятью, но 0.01% нарушает их — эти 0.01% отравят всех.
Потому и получается — то Go породят, отобрав часть рынка, то Rust...
Здравствуйте, m2user, Вы писали:
M>Я полагаю, что такую ошибку покажут статические анализаторы кода.
это слабый аргумент. Как показывает практика статическими анализаторами пользуются не все. А если начинают пользоваться, то ублажать его надо ещё больше чем компилятор Rust. Причём большинство ошибок false-positive. Потому как анализатор прежде всего призван затыкать дырки в языке. В Rust таких false-positive в разы меньше, потому как банально продуман лучше.
Здравствуйте, Shmj, Вы писали:
S>По сути Rust — это просто более строгий язык, который ошибки заменит на этапе компиляции. Примерно как если сравнить C++ и Python — так можно сравнить Rust и C++ — первый более строгий, второй менее.
И?
Вы напишете свой мегапроект на Rust, а не на C++?
Вы начнете штудировать Rust вместо C++ и перестанете захламлять форумы по C++ здесь, на RSDN?
Здравствуйте, Shmj, Вы писали:
S>речь же о смарт указателях и умном управлении памятью
А где у тебя умное управление памятью то?
Там ж фейспалм на фейспалме.
S>Речь про управление памятью с помощью умных указателей. Rust вам просто не позволит чтобы указатель пытались использовать после перемещения.
Если тебе, чтоб не писать ну настолько укуренный код надо чтоб постоянно бил по рукам компилятор — тебе таки да, надо писать исключительно на расте, а во взрослые языки не лезть.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, Shmj, Вы писали:
S>>Что не так? CC>Для начала, у тебя фнукция принимает unique_ptr по значению. Что ты этим хотел сказать?
Ну вот вам с передачей в функцию по ссылке. Что не так:
#include <iostream>
#include <memory>
struct Class1 { const int i1 = 42; };
struct Class2Wrapper
{
Class2Wrapper(std::unique_ptr<Class1> &inner)
{
_inner = std::move(inner);
}
void print() { std::cout << _inner->i1 << std::endl; }
private:
std::unique_ptr<Class1> _inner;
};
void fun1(std::unique_ptr<Class1>& smart_ptr)
{
// Удобно обернули, чтобы удобно использовать
Class2Wrapper wrapper(smart_ptr);
wrapper.print();
}
int main() {
auto smart_ptr = std::make_unique<Class1>();
fun1(smart_ptr); // передали по сслыке, все ОК
std::cout << smart_ptr->i1 << std::endl; // тролололошеньки!!!return 0;
}
Здравствуйте, Нomunculus, Вы писали:
Н>Здравствуйте, Shmj, Вы писали: Н>Ок, пиши на Rust.
Ну так может добавите туда ООП полноценное? Слова то уже зарезервировали, но пока не осилили добавить — ссылаются что это никому не нужно. А вот нужно, ребятки, нужно. ООП — это суровая правда жизни.
Здравствуйте, sergii.p, Вы писали:
S>>Исключения могут летать в методах класса-контейнера при добавлении нового элемента.
SP>тут надо говорить предметно.
Так я вроде и говорю предметно, как человек, которому довелось на коленке пару-тройку подобных примитивных контейнеров слабать.
SP>Лично я всегда перестрахуюсь. Потому как завтра придёт новый человек, подумает почему здесь так всё навёрнуто и совсем упустит момент, что это всё ради exception safety.
Но ведь может прийти человек, который спросит, а зачем мы в C++ тратим ресурсы на то, что должно решаться другими способами? Как бы C++ никогда не был языком, дружественным для новичков. А после взлета Java, C# и Go ему и нет смысла таким оставаться. Это сейчас инструмент для решения задач, для которых пока(?) Java/C#/Scala/Kotlin/F#/Go и пр. не добрались. Поэтому разбрасываться тактами на ровном месте в C++ сейчас не очень понятная идея.
S>>Заключение указателя в optional в C++ общем случае бессмысленно, т.к. этот указатель и есть optional.
SP>ну вот не согласен. Можно сделать метод Person* find() или std::optional<Person*> find(). Во втором обратиться по нулевому указателю намного тяжелее, сложнее на лету вызвать метод find()->name() и т д. В общем, при использовании намного тяжелее не обработать ошибку.
Во втором случае точно так же можно без проблем вызвать find()->name() без предварительных проверок. Т.е. в обоих случаях правильный сценарий использования должен быть таким:
if(auto r = find(); r) {
r->name();
}
И, что характерно, этот код одинаков и для голого указателя, и для optional.
SP>>>как то что не поддерживает ссылки S>>Так ведь это вопрос, по которому консенсуса не смогли найти
SP>что там за консенсус?
Вроде бы вот здесь этот вопрос обсуждался: https://www.fluentcpp.com/2018/10/05/pros-cons-optional-references/
SP>>>operator->() может приводить к UB S>>А вот это как раз понятно.
SP>а вот мне не понятно. Если заботиться о скорости и забить на безопасность, то optional не нужен от слова совсем. Если важна именно безопасность использования, то хотя бы UB уберите из API.
Здравствуйте, Khimik, Вы писали:
K>Это код на Rust? Сорри, я пока его не понимаю, нельзя ли продублировать его на C++, или ещё лучше на Delphi?
Это на C++ с демонстрацией того, что компилятор пропускает очевиднейшую тупую ошибку, которая не возможна в Rust благодаря более современным парадигмам языка.
Здравствуйте, Shmj, Вы писали:
S>Так во в чем вопрос то — почему компилятор позволяет делать вещи, которые заведомо и однозначно ошибочны? Ответ простой — язык не содержит высших парадигм, которые смогли открыть только спустя время, внедрив эти парадигмы в более современные системные языки.
Высшие парадигмы, их содержат только высшие языки, на которых пишут высокую духовную литературу. Санскрит, древнегреческий, древнееврейский, древнекитайский. Боюсь, в современные системные языки эти парадигмы не внедришь, кодировка символов не сойдется. Придется довольствоваться тем, что есть.
Здравствуйте, Shmj, Вы писали:
S>По сути Rust — это просто более строгий язык, который ошибки заменит на этапе компиляции. Примерно как если сравнить C++ и Python — так можно сравнить Rust и C++ — первый более строгий, второй менее.
Я полагаю, что такую ошибку покажут статические анализаторы кода.
(и тут может возникнуть вопрос относительно нужности языка Rust, если можно использовать C/C++ вместе со стат. анализатором).
Например в C# аналогичная ситуация. Компилятор не укажет на ошибочное использование объекта после вызова Dispose, а вот code analysis от MS (с подключенными соотв. правилами) укажет.
Здравствуйте, Alekzander, Вы писали:
A>А теперь посмотри на заголовок темы: "Превосходство Rust над C++". Ты же не уточняешь: "Превосходство Rust над C++ на гипотетическом устройстве, у которого проблемы со стеком" (потому, что в этом случае яркого флейма не выйдет).
Каков размер стека по умолчанию примерно? ˜ 1 МБ или больше?
Т.е. вы не сможете использовать больше 1 Мб памяти по умолчанию в стеке — это даже фотку нельзя обработать.
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, T4r4sB, Вы писали:
TB>>Если же человек говорит что всегда 100% внимателен и никогда не допускает ошибок на внимательность — то с ним всерьёз можно не разговаривать, над ним можно тупо ржать. CC>Там ж даже не ошибка, там тотальное непонимание происходящего.
Да-да, человек читает значения из смувленного объекта лишь потому что не знает что после мува объект скорее всего пустой. А на гололеде падает потому что не знает что от этого можно сломать кости. Вот дурак, это же все кулхацкеры из 9Б знают.
Если человек не знает как возникают такие ошибки на самом деле — то я хз как ему что-то можно объяснить.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, T4r4sB, Вы писали:
TB>>Тебе на индексах, шаред поинтерах или ансейфе шоб 1в1 как в C++? CC>Мне чтоб быстро работал.
Двухсвязный список и шоб быстро работал?
Лучше вектор бери
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, SkyDance, Вы писали:
TB>>Двухсвязный список и шоб быстро работал? TB>> TB>>Лучше вектор бери TB>>
SD>Кто-нибудь может объяснить, в чем именно юмор? И как вообще вектор относится к двусвязному списку?
У двусвязного списка все плохо с кешем.
Кстати а зачем он нужен? Я не моги припомнить таких случаев.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, so5team, Вы писали:
S>Как раз здесь Шмыж, как ни странно, прав.
к сожалению он не так уж редко говорит правильные вещи, но из-за сложившейся репутации эти идеи сразу записывают в маргинальные
По-моему идиому, что конструктор принимает строку по значению, высказывал ещё Майерс, только появилась семантика перемещения. А ведь строка — это и есть по сути unique_ptr.
Здравствуйте, CreatorCray, Вы писали:
CC>Твой наглядный пример:
Так во в чем вопрос то — почему компилятор позволяет делать вещи, которые заведомо и однозначно ошибочны? Ответ простой — язык не содержит высших парадигм, которые смогли открыть только спустя время, внедрив эти парадигмы в более современные системные языки.
Здравствуйте, Shmj, Вы писали:
K>>Это код на Rust? Сорри, я пока его не понимаю, нельзя ли продублировать его на C++, или ещё лучше на Delphi?
S>Это на C++ с демонстрацией того, что компилятор пропускает очевиднейшую тупую ошибку, которая не возможна в Rust благодаря более современным парадигмам языка.
Ой, сорри. Я попросил GPT3 перевести код на Delphi, сильно понятнее не стало. Тут что-то с умными указателями? В строке void fun1(std::unique_ptr<Class1> smart_ptr){} на входе функции fun1 подаётся два параметра или один?
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Здравствуйте, Khimik, Вы писали:
K>Ой, сорри. Я попросил GPT3 перевести код на Delphi, сильно понятнее не стало. Тут что-то с умными указателями? В строке void fun1(std::unique_ptr<Class1> smart_ptr){} на входе функции fun1 подаётся два параметра или один?
Передается 1 параметр — умный указатель на объект типа Class1.
Чтобы понять суть примера, нужно вникнуть в тонкости современного С++ — в старых версиях этих парадигм не было. А именно понять что такое семантика перемещения.
Мы переместили значение — но компилятор разрешает использовать указатель на перемещенное значение. Rust за такое просто бьет по рукам — вы не сможете допустить подобных глупых ошибок.
:
S>Немножко было времени на выходных и по вечерам — почитал учебник Rust. И придумал для таких же как я простой и наглядный пример, который демонстрирует суть владения — зачем оно вообще нужно и в чем смысл. Вот пример:
S>
S>Компилятор С++ это принимает и не пикнет — максимум варнинг выдаст, и то не всегда. А ведь это 100% ошибка без вариантов. А в Rust право владения — суть концепция самого языка.
S>Почему я начал почитывать Rust? Один чел. сказал что разобравшись с Rust — лучше начинаешь понимать другие языки, в частности тот же C++. Ведь в С++ умные указатели ведь тоже завязаны на владение, однако нет парадигмы в самом языке, которая способна выявлять подобные ошибки.
S>По сути Rust — это просто более строгий язык, который ошибки заменит на этапе компиляции. Примерно как если сравнить C++ и Python — так можно сравнить Rust и C++ — первый более строгий, второй менее.
Твой пример показывает (в очередной раз), что правильно подобранный искусственный пример может показать что угодно. Вот тебе ещё более строгий код:
А у тебя на девять строчек — смарт-поинтер, мув-семантика и сорок бочек арестантов. Зачем? Приведи реальный пример, а не из завиральных книжек, и объясни, почему в нём всё вышеперечисленное реально необходимо.
Здравствуйте, Alekzander, Вы писали:
A>Твой пример показывает (в очередной раз), что правильно подобранный искусственный пример может показать что угодно. Вот тебе ещё более строгий код:
A>
A>#include <iostream>
A>struct Class1 { const int i1 = 42; };
A>void fun1(Class1& class1){}
A>int main()
A>{
A> Class1 class1;
A> fun1(class1);
A> std::cout << class1.i1 << std::endl;
A>}
A>
Так у вас нет динамического выделения памяти — речь же о смарт указателях и умном управлении памятью
A>А у тебя на девять строчек — смарт-поинтер, мув-семантика и сорок бочек арестантов. Зачем? Приведи реальный пример, а не из завиральных книжек, и объясни, почему в нём всё вышеперечисленное реально необходимо.
Это не из книжек — в книжках не встречал такого наглядного примера.
Речь про управление памятью с помощью умных указателей. Rust вам просто не позволит чтобы указатель пытались использовать после перемещения.
DP>>Все просто: не нравится — не пиши! Херли ныть ходить
N>Так если популярность языка затащит на него очередные 100500 индусов которые напишут херню и от этого, например, тебя убьёт взбунтовавшимся автомобилем?
Эти проблемы касаются в первую очередь не языка, а других вещей — технологии конструирования автомобилей, тестирования и т.п.
Здравствуйте, CRT, Вы писали:
CRT>так на то он и наглядный (искусственный) чтобы тебе было лучше видно. Это не значит что такое не может произойти в менее наглядном (заметном) виде
Насрать говнокодом — очень наглядно, да.
И раз уж мы про наглядные примеры...
Бензопилой можно дрова порезать а можно ногу отхреначить.
Но в этом не бензопила будет виновата, и даже не кривые ручонки, которые её держали, а тупая башка, которая этим ручонкам говорила что делать. https://www.youtube.com/watch?v=q9A6_MWZ0VY
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Shmj, Вы писали:
S>С непривычки кажется что это сложно. На самом деле вам нужно знать всего 2 вещи:
Хехе.
А теперь покажи doubly linked list
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, CreatorCray, Вы писали:
S>>Вы начнете штудировать Rust вместо C++ и перестанете захламлять форумы по C++ здесь, на RSDN? CC>А было бы неплохо...
Здравствуйте, CreatorCray, Вы писали:
S>>речь же о смарт указателях и умном управлении памятью CC>А где у тебя умное управление памятью то? CC>Там ж фейспалм на фейспалме.
Экземпляр класса Class1 создали в куче и ссылаемся с помощью умного указателя — по выходу из функции — он будет уничтожен без ручного вызова delete.
В стеке может просто не быть места на размещение.
Что не так?
S>>Речь про управление памятью с помощью умных указателей. Rust вам просто не позволит чтобы указатель пытались использовать после перемещения. CC>Если тебе, чтоб не писать ну настолько укуренный код надо чтоб постоянно бил по рукам компилятор — тебе таки да, надо писать исключительно на расте, а во взрослые языки не лезть.
Так это же тривиальный пример. Может быть такое, что вы заменяете обычные указатели на умные и не заметили как в какой-то из функци произошла передача владения.
Здравствуйте, Shmj, Вы писали:
A>>Твой пример показывает (в очередной раз), что правильно подобранный искусственный пример может показать что угодно. Вот тебе ещё более строгий код:
A>>
S>Так у вас нет динамического выделения памяти — речь же о смарт указателях и умном управлении памятью
Я считаю, что некоторые вещи, скажем так, не очевидны. Например, что обобщённое программирование, если по-хорошему, за пределами стандартной библиотеки (любого языка) не сильно нужно и повод напрячься. В основном, оно нужно для контейнеров. И ну оооооочень редко ты видишь прикладной код, который можно обобщённо переписать, и он будет DRY'истее и понятнее. Если ты пишешь такой код часто, или часто ваяешь свои контейнеры (и они реально нужны при наличии самых разных стандартных библиотек), ты должен понимать, что таких, как ты — исчезающе малая доля. И прогибать язык под такие сценарии это безумие. В Майкрософте это понимают, поэтому дотнет это дотнет. А степанов не понимает. Поэтому сиплюсплюс это сиплюсплюс.
Поэтому я и предложил: прежде, чем сравнивать C++ с Rust'ом в плане надёжности, подбери такой пример, который средний программист мог бы написать. И покажи, что его нельзя никак переписать на самом C++, чтобы он стал не менее безопасным, чем Rust. И очень многое сразу станет понятно.
Пример: я спрашивал давеча, как написать is in set на плюсах. Чтобы он был выразителен и не был медленнее (x == .. || x == .. || ...). Это то, что пишется чуть ли не в каждом проекте. Именно на таких примерах и стоит обсуждать достоинства и недостатки языков. Желающих только нет. Там и обсуждать нечего: можешь написать — напиши. А не можешь — значит не можешь.
A>>А у тебя на девять строчек — смарт-поинтер, мув-семантика и сорок бочек арестантов. Зачем? Приведи реальный пример, а не из завиральных книжек, и объясни, почему в нём всё вышеперечисленное реально необходимо.
S>Это не из книжек — в книжках не встречал такого наглядного примера.
Здравствуйте, Shmj, Вы писали:
S>В стеке может просто не быть места на размещение.
S>Что не так?
Я объясню, что не так.
Ты пишешь про гипотетическое устройство, у которого проблемы со стеком и надо, воленс-неволенс, размещать всё в куче. Такие устройства, кстати, реально существовали — одно из них называлось Handheld PC под управлением Windows Mobile (версии до 5-й включительно... кажется). Кто под неё писал большие проекты, тот помнит эту вечную охоту на ведьм: кто сожрал весь стек
А теперь посмотри на заголовок темы: "Превосходство Rust над C++". Ты же не уточняешь: "Превосходство Rust над C++ на гипотетическом устройстве, у которого проблемы со стеком" (потому, что в этом случае яркого флейма не выйдет). И даже не уточняешь: "Превосходство Rust над C++ на карманных компьютерах под Windows Mobile" (потому, что кроме археологов это никому не интересно). Нет, безо всяких оговорок: превосходство, и всё тут.
Зачем это всё? Тебе платят за поддержку полуживого RSDN'а на плаву? Или, как в том анекдоте, "А поговорить"?
Здравствуйте, T4r4sB, Вы писали:
TB>Если же человек говорит что всегда 100% внимателен и никогда не допускает ошибок на внимательность — то с ним всерьёз можно не разговаривать, над ним можно тупо ржать.
Там ж даже не ошибка, там тотальное непонимание происходящего.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Shmj, Вы писали:
S>Что не так?
Для начала, у тебя фнукция принимает unique_ptr по значению. Что ты этим хотел сказать?
S>Может быть такое, что вы заменяете обычные указатели на умные
Если уж речь идёт о рефакторинге говнокода, раз уж там голые указатели везде, то первым проходом всё что только можно меняется на ссылки
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Shmj, Вы писали:
S>Компилятор С++ это принимает и не пикнет — максимум варнинг выдаст, и то не всегда. А ведь это 100% ошибка без вариантов.
В этом и прелесть С++. Ты делаешь то, что хочешь. Однако, если ты не понимаешь что ты делаешь, то зачем вообще что-то писать?
S>Почему я начал почитывать Rust?
Лучше что-то писать на нём.
Что можно доказать, если к предыдущей реализации не возникло претензий? Вот если попробовать реализовать двусвязный список на С++ не на голых указателях, всё равно ведь придём к подобной реализации на shared_ и weak_ptr. Ну можно сократить на optional. И вовсе не из-за того что в Rust запрещены нулевые указатели, а из-за того что optional в С++ настолько калечный, что проще без него.
Здравствуйте, Shmj, Вы писали:
A>>А теперь посмотри на заголовок темы: "Превосходство Rust над C++". Ты же не уточняешь: "Превосходство Rust над C++ на гипотетическом устройстве, у которого проблемы со стеком" (потому, что в этом случае яркого флейма не выйдет).
S>Каков размер стека по умолчанию примерно? ˜ 1 МБ или больше?
S>Т.е. вы не сможете использовать больше 1 Мб памяти по умолчанию в стеке — это даже фотку нельзя обработать.
Ну, это уже передёргивание. Никто тут не говорил, что не надо пользоваться кучей. Вопрос был, зачем в данном конкретном случае писать такие ужасы. С просьбой заменить искусственный пример хоть сколько-нибудь реальным. В ответ прозвучало, мол, у нас в стек ничего не влезет.
Вот я смотрю на свой код, который делает снимки экрана и ресайзит их, и там нет ничего из того, что есть в твоём примере. Он работает с кучей, но неявно. И контейнер изображения (кстати, библиотечный) передаётся в аналог fun1() по ссылке. Ссылке, простой как три рубля.
Здравствуйте, Alekzander, Вы писали:
A>Ну, это уже передёргивание. Никто тут не говорил, что не надо пользоваться кучей. Вопрос был, зачем в данном конкретном случае писать такие ужасы. С просьбой заменить искусственный пример хоть сколько-нибудь реальным. В ответ прозвучало, мол, у нас в стек ничего не влезет.
Здравствуйте, SkyDance, Вы писали:
SD>Кто-нибудь может объяснить, в чем именно юмор? И как вообще вектор относится к двусвязному списку?
Да у него сова не налазит и потому он Камалу включает — начинает ржать.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Shmj, Вы писали:
S>Ну вот вам с передачей в функцию по ссылке. Что не так:
S> Class2Wrapper(std::unique_ptr<Class1> &inner) S> { S> _inner = std::move(inner); S> }
Это очевиднейший говнокод.
Переделывай на &&
А как переделаешь — в другом месте вылезет очевидность
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Shmj, Вы писали:
S>Но компилятор даже warning не выдал
А должен?
Компилятор не обязан угадывать что именно хотел сделать пейсатель. Если бы мог — писал бы код сам, без привлечения кожаных мешков.
S>А ведь в более развитых системных языках — такое отлавливается на уровне компиляции.
Отсутсвие мыслительного процесса в межушном ганглии не отлавливается ничем.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, sergii.p, Вы писали:
SP>Что можно доказать, если к предыдущей реализации не возникло претензий? Вот если попробовать реализовать двусвязный список на С++ не на голых указателях, всё равно ведь придём к подобной реализации на shared_ и weak_ptr.
А зачем? Какой смысл в C++ внутри Node использовать умные указатели, да еще и с подсчетом ссылок?
По идее, Node должны быть под капотом в каком-то классе-контейнере. И деструктор этого контейнера простым циклом удаляет все содержимое.
Если удаление не делать простым циклом, а полагаться на вызовы деструкторов, то при больших размерах списков можно переполнить стек рекурсией вызова деструкторов. Ну а раз ручной цикл в деструкторе контейнера нужен, то в чем смысл умных указателей в Node?
SP>Ну можно сократить на optional. И вовсе не из-за того что в Rust запрещены нулевые указатели, а из-за того что optional в С++ настолько калечный, что проще без него.
В C++ std::optional<some_type*> сам по себе имеет мало смысла. Разве что для тех редких ситуаций, когда nullptr входит в число легальных значений и нам нужно понимать есть ли вообще какое-то значение (включая nullptr) или нет. Но в таких случаях std::optional вовсе не калечный, т.к. nullptr не может использоваться как признак отсутствия значения, все равно нужен еще один bool.
Если же nullptr в число легальных значений не входит, то простой some_type* работает не хуже std::optional<some_type*>. И optional нужен разве что в случае, когда код написан с расчетом именно на optional, т.е. с использованием has_value, value, then (из новых стандартов).
Здравствуйте, Shmj, Вы писали:
S>Но компилятор даже warning не выдал S>А ведь в более развитых системных языках — такое отлавливается на уровне компиляции.
Ну, дело за малым — развитым системным язком с детектором ошибок в ДНК "программиста" и вызовом утилизационной бригады.
Здравствуйте, so5team, Вы писали:
S>А зачем? Какой смысл в C++ внутри Node использовать умные указатели, да еще и с подсчетом ссылок?
ну банально чтобы не получить утечку памяти. Ручное удаление может не так уж плохо в С, а в С++ летают исключения — RAII скорей не роскошь, а необходимость.
S>В C++ std::optional<some_type*> сам по себе имеет мало смысла. Разве что для тех редких ситуаций, когда nullptr входит в число легальных значений и нам нужно понимать есть ли вообще какое-то значение (включая nullptr) или нет. Но в таких случаях std::optional вовсе не калечный, т.к. nullptr не может использоваться как признак отсутствия значения, все равно нужен еще один bool.
S>Если же nullptr в число легальных значений не входит, то простой some_type* работает не хуже std::optional<some_type*>. И optional нужен разве что в случае, когда код написан с расчетом именно на optional, т.е. с использованием has_value, value, then (из новых стандартов).
первый случай тяжело представить в реальном мире, а второй вариант прекрасно реализован во многих языках. Что мешало сделать перегрузку и в С++?
А калечный optional в частности потому что "some_type* работает не хуже". То есть применение бессмысленно. Я уж не говорю про другие проблемы, как то что не поддерживает ссылки, до С++23 нет монадических интерфейсов, operator->() может приводить к UB. В общем коммитет постарался даже лучше чем Бог над черепахой.
Здравствуйте, sergii.p, Вы писали:
S>>А зачем? Какой смысл в C++ внутри Node использовать умные указатели, да еще и с подсчетом ссылок?
SP>ну банально чтобы не получить утечку памяти. Ручное удаление может не так уж плохо в С, а в С++ летают исключения — RAII скорей не роскошь, а необходимость.
Исключения могут летать в методах класса-контейнера при добавлении нового элемента. Там нужно обеспечивать exception safety в любом случае. И там это можно делать за счет, например, временного помещения нового элемента, еще не провязанного в список, в std::unique_ptr с последующим вызовом release при успешном окончании. Так что смысла хранить внутри Node умные указатели нет (ну разве что std::unique_ptr, если контейнер пишется наспех и нет ресурсов делать хорошую реализацию).
SP>первый случай тяжело представить в реальном мире,
Это да.
SP>Что мешало сделать перегрузку и в С++?
Хороший вопрос.
SP>А калечный optional в частности потому что "some_type* работает не хуже". То есть применение бессмысленно.
Заключение указателя в optional в C++ общем случае бессмысленно, т.к. этот указатель и есть optional.
SP>как то что не поддерживает ссылки
Так ведь это вопрос, по которому консенсуса не смогли найти
Было бы у всех однозначное отношение, была бы поддержка или было бы очевидно, почему ее нет.
Ну а так как в C++ приходится удовлетворять разные группы пользователей, то иногда лучше не дать чего-то, чем дать то, что вызовет лютую ненависть у значительной части пользователей.
SP>до С++23 нет монадических интерфейсов
Обычная эволюция. Корни же растут из boost::optional лохматых нулевых годов, тогда в C++ монадическими интерфейсами даже Александреску не занимался
SP>operator->() может приводить к UB
А вот это как раз понятно. Дали возможность максимально дешевого обращения к содержимому переложив ответственность на программиста. Так же, как в std::vector есть operator[[] и at
TB>У двусвязного списка все плохо с кешем. TB>Кстати а зачем он нужен? Я не моги припомнить таких случаев.
Вообще именно список — для быстрого удаления/добавления в середине.
Двухсвязный — для итерации в оба направления при поиске элемента.
На удивление, не столь бесполезны как кажется — на них lock-less контейнеры чудят.
Здравствуйте, so5team, Вы писали:
S>Исключения могут летать в методах класса-контейнера при добавлении нового элемента.
тут надо говорить предметно. Лично я всегда перестрахуюсь. Потому как завтра придёт новый человек, подумает почему здесь так всё навёрнуто и совсем упустит момент, что это всё ради exception safety.
S>Заключение указателя в optional в C++ общем случае бессмысленно, т.к. этот указатель и есть optional.
ну вот не согласен. Можно сделать метод Person* find() или std::optional<Person*> find(). Во втором обратиться по нулевому указателю намного тяжелее, сложнее на лету вызвать метод find()->name() и т д. В общем, при использовании намного тяжелее не обработать ошибку.
SP>>как то что не поддерживает ссылки S>Так ведь это вопрос, по которому консенсуса не смогли найти
что там за консенсус?
SP>>operator->() может приводить к UB S>А вот это как раз понятно.
а вот мне не понятно. Если заботиться о скорости и забить на безопасность, то optional не нужен от слова совсем. Если важна именно безопасность использования, то хотя бы UB уберите из API.
В целом, складывается ощущение что в C++ optional просто не лезет по целой гамме причин. И зачем такого уродца родил коммитет, совсем не ясно. Лучше взять было стороннюю библиотеку, которая тебя полностью удовлетворяет. А сейчас даже сторонню тяжело взять. Любой на ревью спросит: "да зачем, в стандарте же есть".
Здравствуйте, Shmj, Вы писали:
S>... S>Компилятор С++ это принимает и не пикнет — максимум варнинг выдаст, и то не всегда. А ведь это 100% ошибка без вариантов. А в Rust право владения — суть концепция самого языка.
C++ даёт возможность расстреливать ноги огромным количеством способов, а Rust — не даёт. Вот это новость!
Здравствуйте, so5team, Вы писали:
S>void push_to_processing(std::unique_ptr<Transaction> trx); S>Так что наличие std::unique_ptr<T> как аргумент по значению однозначно указывает на то, что вызываемая функция забирает и объект, и ответственность за его дальнейшую судьбу себе.
Core Guide говорит использовать такой подход, но есть ли тут гарантия совместимости если push_to_processing это функция из библиотеки которая собранна другой версией компилятора?
Нашел у себя такой код завязянный на Qt:
auto data = std::unique_ptr<QSurfaceDataArray>(new QSurfaceDataArray);
...
// series takes ownership
m_powerSeries->dataProxy()->resetArray(data.release());
Думаю, что resetArray принимает владение через голый указатель именно для гарантии бинарной соместимости.
Здравствуйте, Skorodum, Вы писали:
S>>void push_to_processing(std::unique_ptr<Transaction> trx); S>>Так что наличие std::unique_ptr<T> как аргумент по значению однозначно указывает на то, что вызываемая функция забирает и объект, и ответственность за его дальнейшую судьбу себе. S>Core Guide говорит использовать такой подход, но есть ли тут гарантия совместимости если push_to_processing это функция из библиотеки которая собранна другой версией компилятора?
Если заботиться о разных версиях компилятора и stdlib, то передача вообще чего-либо C++ного по значению, имхо, становится проблемой (да и не по значению тоже стрёмно). И в проектах, где на это заморачиваются, выставляют наружу обычный plain C интерфейс, afaik.
Здравствуйте, Shmj, Вы писали:
S>И придумал для таких же как я простой и наглядный пример
Ты палатой ошибся. Здесь уже вылеченные от "прыжков по языкам" люди. А ты всё как Рогозин, пытаешься улететь в космос на батуте. К чему ты заводишь свои тухлые топики с Растом? У тебя что, чесотка? Успокойся, ПИШИ НА РАСТ, зачем ты людей дёргаешь? Или ты нутром всё же понимаешь, что ковыряешься в говне, но пытаешься выглядеть выше даже C#-щиков?
Здравствуйте, Baiker, Вы писали:
B>Ты палатой ошибся. Здесь уже вылеченные от "прыжков по языкам" люди. А ты всё как Рогозин, пытаешься улететь в космос на батуте. К чему ты заводишь свои тухлые топики с Растом? У тебя что, чесотка? Успокойся, ПИШИ НА РАСТ, зачем ты людей дёргаешь? Или ты нутром всё же понимаешь, что ковыряешься в говне, но пытаешься выглядеть выше даже C#-щиков?
Так как бы не очень хочется, но объективно вынужден признать что парадигмы более строгие.
Здравствуйте, sergii.p, Вы писали:
SP>ну банально чтобы не получить утечку памяти. Ручное удаление может не так уж плохо в С, а в С++ летают исключения — RAII скорей не роскошь, а необходимость.
Ты правда хочешь кидать исключения из деструктора?
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Не подскажите, как можно в си++ написать функцию которая считывает и возвращает строку, вызывается в майн и печатается на экране.
Дело в том что я написал ее на раст, а вот на зиг который требует для этого управлением памятью, падает в рантайм с ошибкой утечки памяти.
На раст это оказалось сделать несложно относительно зига, конечно.
Здравствуйте, Разраб, Вы писали:
Р>Не подскажите, как можно в си++ написать функцию которая считывает и возвращает строку, вызывается в майн и печатается на экране. Р>Дело в том что я написал ее на раст, а вот на зиг который требует для этого управлением памятью, падает в рантайм с ошибкой утечки памяти. Р>На раст это оказалось сделать несложно относительно зига, конечно.
Откройте для себя GPT.
C++
#include <iostream>
#include <string>
// Функция для считывания строки с клавиатуры
std::string readStringFromInput() {
std::string inputString;
std::cout << "Введите строку: ";
std::getline(std::cin, inputString);
return inputString;
}
int main() {
// Вызываем функцию для считывания строки
std::string str = readStringFromInput();
// Выводим считанную строку на экран
std::cout << "Вы ввели строку: " << str << std::endl;
return 0;
}
Rust:
use std::io;
// Функция для считывания строки с клавиатурыfn read_string_from_input() -> String {
let mut input_string = String::new();
println!("Введите строку:");
io::stdin().read_line(&mut input_string).expect("Ошибка при считывании строки");
input_string
}
fn main() {
// Вызываем функцию для считывания строкиlet str = read_string_from_input();
// Выводим считанную строку на экран
println!("Вы ввели строку: {}", str);
}
Здравствуйте, CreatorCray, Вы писали:
CC>Ты правда хочешь кидать исключения из деструктора?
не вижу связи. По вашему получается, если человек использует умные указатели, то он хочет кидать исключения из деструктора? Я просто хотел сказать, что в С++ умные указатели более востребованы из-за непредсказуемой последовательности действий. В С мы можем быть точно уверены, что дойдём до конца функции и вызовем очистку памяти, а в С++ любое исключение вносит долю неопределённости.
Здравствуйте, Khimik, Вы писали: K>Ой, сорри. Я попросил GPT3 перевести код на Delphi, сильно понятнее не стало. Тут что-то с умными указателями? В строке void fun1(std::unique_ptr<Class1> smart_ptr){} на входе функции fun1 подаётся два параметра или один?
Тут основная шутка в том что это написал человек не понимающий ассемблера или же просто очень острый шутник. На самом деле std move ничего не перемещает. Объект остается на стеке или в регистрах и спокойно переиспользуетмя. Формально там ошибка (нуачо, объект же был перемещен) по факту нет
B>Ты палатой ошибся. Здесь уже вылеченные от "прыжков по языкам" люди. А ты всё как Рогозин, пытаешься улететь в космос на батуте. К чему ты заводишь свои тухлые топики с Растом? У тебя что, чесотка? Успокойся, ПИШИ НА РАСТ, зачем ты людей дёргаешь? Или ты нутром всё же понимаешь, что ковыряешься в говне, но пытаешься выглядеть выше даже C#-щиков?