Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[13.59.136.170] |
|
Страницы: (32) « Первая ... 24 25 [26] 27 28 ... 31 32 ( Перейти к последнему сообщению ) |
Сообщ.
#376
,
|
|
|
Сообщ.
#377
,
|
|
|
Так норм? #include <fcntl.h> #include <sys/stat.h> bool ReadFile(std::string iFileName, std::string *iContent) { auto close_file = [](int *iFp) { close(*iFp); }; auto Fp = std::unique_ptr<int, decltype(close_file)> ( new int(open(iFileName.c_str(), O_RDONLY)), close_file); int Fd = *Fp.get(); if (Fd < 0) return false; struct stat Sb; if (fstat(Fd, &Sb) < 0) return false; iContent->resize(Sb.st_size); if (read(Fd, const_cast<char *>(iContent->data()), Sb.st_size) < 0) return false; return true; } |
Сообщ.
#378
,
|
|
|
Цитата JoeUser @ Так норм? А чем тебя std::ifstream не устроил? std::unique_ptr - с указателями работает, я бы на крайняк взял уже FILE* fopen/fclose. А так у тебя костыль какой то + утечка памяти(под int* память выделил, а не освободил). Добавлено Если тебе нужно использовать вот только именно эти функции, по религиозным убеждениям, тогда лучше самому написать класс обертку. умные указатели работают как бы с указателями Добавлено Уж лучше как то так переписать тогда: auto close_file = [](FILE* pFile) { fclose(pFile); }; auto Fp = std::unique_ptr<FILE, decltype(close_file)> (fopen(iFileName.c_str(), O_RDONLY),close_file); Но вообще судя по std::string, я бы юзал std::ifstream. |
Сообщ.
#379
,
|
|
|
Цитата Wound @ А чем тебя std::ifstream не устроил? Тормозючий. Цитата Wound @ А так у тебя костыль какой то + утечка памяти(под int* память выделил, а не освободил). А еcли так? #include <fcntl.h> #include <sys/stat.h> bool ReadFile(std::string iFileName, std::string *iContent) { auto close_file = [](int *iFp) { close(*iFp); delete iFp; }; auto Fp = std::unique_ptr<int, decltype(close_file)> ( new int(open(iFileName.c_str(), O_RDONLY)), close_file); int Fd = *Fp.get(); if (Fd < 0) return false; struct stat Sb; if (fstat(Fd, &Sb) < 0) return false; iContent->resize(Sb.st_size); if (read(Fd, const_cast<char *>(iContent->data()), Sb.st_size) < 0) return false; return true; } |
Сообщ.
#380
,
|
|
|
Цитата JoeUser @ Тормозючий. Ок, FILE* fopen/fclose - чем не угодил? Цитата JoeUser @ А еcли так? Да костыль это. Ты делаешь какое то левое телодвижение для того, чтоб у тебя скомпилировалось. Это не айс. Добавлено Нет, оно так конечно будет работать, и все по принципу RAII - но меня лично смущает что ты по факту выделяешь 2 ресурса в одной обертке. |
Сообщ.
#381
,
|
|
|
Цитата Wound @ Ок, FILE* fopen/fclose - чем не угодил? Не такой тормозючий как std::ifstream, но чуть медленнее POSIX варианта. Я не про открытие, а про read/write. Цитата Wound @ Да костыль это. Ты делаешь какое то левое телодвижение для того, чтоб у тебя скомпилировалось. Это не айс. Ну нужен мне open, что тут поделать? |
Сообщ.
#382
,
|
|
|
Цитата JoeUser @ Ну нужен мне open, что тут поделать? Пиши класс обертку тогда. Так будет правильнее. Либо, можно посмотреть какую нить фичу в С++, которая конвертирует тип в указатель. |
Сообщ.
#384
,
|
|
|
В среднем fread быстрее. Добавлено Вообще они одинаковы. Видно же. А то что там на пару милисикунд где то POSIX Обогнал - это скорее всего от функций вообще не зависит, винт подзадумался небось вот и разница. |
Сообщ.
#385
,
|
|
|
Цитата Wound @ В среднем fread быстрее. Не, в 4-x из 18 тестов - быстрее. А в остальных 14 - проигрывает. Добавлено Цитата Wound @ Нет, оно так конечно будет работать, и все по принципу RAII Все равно выше у меня было неправильно Вот теперь должно быть правильно: #include <fcntl.h> #include <sys/stat.h> bool ReadFile(std::string iFileName, std::string *iContent) { auto close_file = [](int *iFp) { if (*iFp>=0) close(*iFp); delete iFp; }; auto Fp = std::unique_ptr<int, decltype(close_file)> ( new int(open(iFileName.c_str(), O_RDONLY)), close_file); int Fd = *Fp.get(); if (Fd < 0) return false; struct stat Sb; if (fstat(Fd, &Sb) < 0) return false; iContent->resize(Sb.st_size); if (read(Fd, const_cast<char *>(iContent->data()), Sb.st_size) < 0) return false; return true; } |
Сообщ.
#386
,
|
|
|
Там написано "и прочее", куда вполне может входить и Delphi. Невнимательность? Впрочем, ты прав, в мое "и прочее" Delphi не входит, но когда-то очень давно туда входил его брат C++ Builder. А что не так с Delphi?
Цитата Qraizer @ А зачем так писать? Заворачиваем в функцию и вызываем сколько угодно раз не парясь об освобождении ресурса. Смотри ответ Дикею ниже.Это прекрасно, пока не встретишь auto res1 = PQExec(...); scope(exit) PQClear(res1); auto res2 = PQExec(...); scope(exit) PQClear(res1); auto res3 = PQExec(...); scope(exit) PQClear(res1); Цитата D_KEY @ Конечно. RAII - это прекрасная технология, особенно если нужен именно объект владеющий ресурсом. А вот в случае когда нужен скоуп владеющий ресурсом, RAII зачастую совершенно излишен. Ты, видимо, совсем мало использовал ФП иначе знал бы об этом. Угадай, как функциональщики без всяких RAII управляют, допустим, транзакциями в БД? Я тоже пробовал много чего, в том числе и то, что указал ты (кроме elixir, да и D мало слишком). Я не считаю C++ лучшим или что-то такое, но вот RAII очень крутая (и при этом простая) концепция. Цитата D_KEY @ Инерция мышления, однако. Очевидно, если захват и освобождение ресурса необходимо повторить много раз, пишется обертка, только не класс, а функция, которая нередко (но не всегда) оказывается проще и понятнее RAII аналога:Ага, это пока в очередной раз фигача подобный код ты не забудешь воткнуть свой scope(exit). Нафиг. Владелец пишется один раз (благодаря умным указателям это иногда просто typedef/using), используется потом много где просто как: auto res = PQExec(...); Сравнивай. Result exec(...) { auto res = PQExec(...); scope(exit) PQClear(res); ... return Result(res); } auto res = exec(...); Сравнивай. В таком случае вероятность забывания написания scope равна вероятности забывания написания деструктора. Цитата D_KEY @ Сам по себе ООП нет, а вот образ мышления, который навязывает мейнстримовый ООП (который на трех китах) очень даже имеет. Ну и не забываем, что scope() может рулить чем угодно, например, теми же транзакциями в БД или мьютексами, а всякие xxxx_ptr только указателями.ООП не имеет никакого отношения к теме. Совсем. Я бы даже сказал, что без GC нормального ООП быть не может, но чистые плюсовики меня растерзают, поэтому я не стану этого говорить Обертку во многих случаях даже писать не придется - есть unique_ptr и shared_ptr. Напишешь один using и вперед. Цитата Wound @ Прочитал. scope(exit) там не причем. С тем же успехом можно сегфолтнуть и в деструкторе RAII обертки. Чувак просто не знал, что в D (как и в Java и, наверное, в C#, поправь если не так) объекты на куче автоматически не дестроятся при выходе из скоупа, так как этим занимается GC. А вот объекты на стеке дестроятся автоматически как и в C++. Я же ссылку привел выше, ок продублирую еще раз: https://forum.dlang.org/thread/kjkdfcnpgdeg...forum.dlang.org Вот тут чувак выхватил сигфолт благодаря GC и scope(exit). |
Сообщ.
#387
,
|
|
|
Цитата applegame @ Прочитал. scope(exit) там не причем. С тем же успехом можно сегфолтнуть и в деструкторе RAII обертки. Чувак просто не знал, что в D (как и в Java и, наверное, в C#, поправь если не так) объекты на куче автоматически не дестроятся при выходе из скоупа, так как этим занимается GC. А вот объекты на стеке дестроятся автоматически как и в C++. Нет, не с тем же успехом. Если убрать его багу, допустим выкинуть scope(exit) вообще из его программы, никаких сигфолтов нет. Его программа абсолютна правильная и рабочая на языке D. Но не в С++, вот в этом и состоит существенная разница. Для С++ эта программа багнутая. Поэтому в D - ты можешь выхватить очень просто этот сигфолт, потому что тебе нужно этот ньюанс держать в голове. А в С++, если следовать всем правилам - такой ситуации просто не получится. Потому что раз там указатель и память выделяется по new, значит это так же оборачивается в RAII обертку. А она сама знает когда нужно вызвать деструктор. Ну я не знаю с чем ты споришь. В Dшном примере - ручное управление ресурсом в перемешку с автоматическим GC. В С++ если это все обернуть в RAII обертки - полностью автоматическое управление ресурсом. Добавлено Если я неясно выразился, поясню на примере: Возьмем вариант D. Было: import std.stdio; struct De { ~this() { writeln("De"); } } void main() { De a; scope(exit) writeln("scope exit"); De b; } Все работало правильно. Потом пришел Вася, и с бодуна поправил какой то баг: import std.stdio; struct De { ~this() { writeln("De"); } } void main() { auto a = new De(); scope(exit) writeln("scope exit"); De b; } И опля - породил еще один баг. Вася просто не увидел scope(exit), думал о другом, еще что то там. А в С++ если вася так исправит - это не пройдет код ревью, либо он заведомо напишет баг, память по new выделил, а удалить то забыл, тю тю. А если вася грамотный, он естественно будет писать RAII обертки, и у него такой ситуации просто не возникнет. |
Сообщ.
#388
,
|
|
|
Цитата Wound @ Ну так в моем случае оно тоже автоматическое. Точнее, я только в одном месте использую scope, а далее просто вызываю функцию. Точно так же ты, делая обертку в дуструкторе вручную освобождаешь ресурсы. Вопрос исключительно в простоте, понятности и читабельности. В C++ у тебя особо-то и выбора нет, в отличие от того же D, где ты можешь использовать и RAII и scope(exit) в зависимости от ситуации. С появлением в плюсах лямбд стало несколько попроще, некоторые плюсовики даже внезапно открыли для себя ФП техники давно применяющиеся в том же D . Но лямбды в плюсах, как и все остальное, получились страшными, как атомная война. Поэтому, видимо, с таким скрипом и удивлением люди узнают, что помимо их любимых, казавшихся единственными и самыми правильными техниками, существуют и другие более простые, понятные и не менее безопасные техники.Ручное управление ресурсом - всегда хуже автоматического, потому как является источником многих косяков и багов. Как я тебя понимаю, сам таким был несколько лет назад. |
Сообщ.
#389
,
|
|
|
Цитата Wound @ Пиши класс обертку тогда. В принципе, я помню пост Qraizer'а. Но мне кажется, что по накладным расходам они очень близки. Но у него Guard на стеке. Поэтому переделываем еще, чтобы быть не хуже bool ReadFile(std::string iFileName, std::string *iContent) { int Place; auto close_file = [](int *iFp) { if (*iFp >= 0) close(*iFp); }; auto Fp = std::unique_ptr<int, decltype(close_file)> ( new (&Place) int(open(iFileName.c_str(), O_RDONLY)), close_file); int Fd = *Fp.get(); if (Fd < 0) return false; struct stat Sb; if (fstat(Fd, &Sb) < 0) return false; iContent->resize(Sb.st_size); if (read(Fd, const_cast<char *>(iContent->data()), Sb.st_size) < 0) return false; return true; } И утечки нет, и все на стеке сидит (за исключением хитрого указателя, у него кишки небойсь в куче?). |
Сообщ.
#390
,
|
|
|
Цитата applegame @ Ну так в моем случае оно тоже автоматическое. Точнее, я только в одном месте использую scope, а далее просто вызываю функцию. Точно так же ты, делая обертку в дуструкторе вручную освобождаешь ресурсы. Вопрос исключительно в простоте, понятности и читабельности. В C++ у тебя особо-то и выбора нет, в отличие от того же D, где ты можешь использовать и RAII и scope(exit) в зависимости от ситуации. С появлением в плюсах лямбд стало несколько попроще, некоторые плюсовики даже внезапно открыли для себя ФП техники давно применяющиеся в том же D . Но лямбды в плюсах, как и все остальное, получились страшными, как атомная война. Поэтому, видимо, с таким скрипом и удивлением люди узнают, что помимо их любимых, казавшихся единственными и самыми правильными техниками, существуют и другие более простые, понятные и не менее безопасные техники. Чем твоя функция будет отличаться от Сишной функции с теми же goto ? Добавлено Цитата applegame @ Точно так же ты, делая обертку в дуструкторе вручную освобождаешь ресурсы. Вопрос исключительно в простоте, понятности и читабельности. В C++ у тебя особо-то и выбора нет, в отличие от того же D, где ты можешь использовать и RAII и scope(exit) в зависимости от ситуации. Я думаю, что если бы этот scope(exit) был таким же крутым как RAII, то во всяких Java/C# он давно бы уже был, вместо этих ваших using/try-with-resources, которые имитируют как раз RAII, с принудительным вызовом деструктора. Добавлено Потому что как показывает практика, выделять ресурс никто не забывает в основном, забывают написать освобождение ресурса, либо делают его не в том порядке, либо сама программа спроектирована так, что вызывает эти функции очистки не в том порядке, что приводит к ошибкам. Конечно - когда ты тут показываешь 3 строчки кода - тут все красиво и понятно, а когда есть большой проект, то становится все не так очевидно. В случае с RAII ты пишешь инициализацию/удаление отдельно, и забыть написать удаление - конечно можно, но это довольно не тривиальная задача. А потом просто юзай и все, не заботясь о том в каком там порядке что у тебя вызывается, или когда там нужно очистить если исключение произошло или еще что то, сам компилятор за тебя все очистит правильно и гарантированно в нужном порядке. |