Прогнал дебагером интереса ради, действительно в первом случае после конструктора вызывается деструктор, который выполняет delete[].
Думаю что вариант с "умным" указателем даже предпочтительней чем вектор для выделения таких "одноразовых" буферов для API.
Что касается второго случая, то действительно все равно происходит копирование, что-то я тупанул. Перемещать он умеет только строки в строки, все остальное будет копировать.
D>> string path(std::move(&buff[0])); //Действительно ли это будет оптимальней, нежели string path(&buff[0])
W>
W>Оптимальней не будет, лучше выбрать вариант без std::move. W>У фундаментальных типов (у указателя в данном случае) вообще нет перемещающих конструкторов — всё делается через копирование. Ну и смысла в существовании перегрузки конструктора string, принимающего r-value ссылку на указатель, тоже нет никакого по этим причинам. Так что стоит предпочесть более короткий и понятный код.
И для закрепления: скажем есть функция, которая возвращает например string. Ну вот так:
string SomeFunction()
{
string ResultString{};
....
// тут мы эту сроку заполняем
....
return ResultString; //или все же надо return std::move(ResultString)?
}
//последующий вызов например
string a{SomeFunction()};
string b = SomeFunction() + "qwerty";
//и т.п.
Я так понимаю, что результаты работы функции априори возвращаются как r-value и при наличии перемещающего конструктора будет перемещен, а явно указывать это нет необходимости?
Здравствуйте, dosik, Вы писали:
D>В продолжении разговора, вот вторая реанкорнация с вкусностями С++11. D>Посмотрите, нет ли тут утечки памяти: D>
D> size_t size = MAX_PATH;
D> std::unique_ptr<char[]> buff(new char[size]);
D> DWORD mfn_size = GetModuleFileName(NULL, &buff[0], size);
D> while (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
D> {
D> size *= 2;
D> buff = std::unique_ptr<char[]>(new char[size]); //Происходит ли удаление старого буфера тут?
D> mfn_size = GetModuleFileName(NULL, &buff[0], size);
D> }
D> string path(std::move(&buff[0])); //Действительно ли это будет оптимальней, нежели string path(&buff[0])
D>
Во-первых, можно использовать юникодную версию функции и сразу выделить буфер в 32К. Во-вторых, unique_ptr тут, вероятно, не нужен, т.к. все это можно сделать так же коротко и с обычным вектором (vector::resize). В-третьих, функция GetModuleFileNameA не может вернуть путь длиннее MAX_PATH, поэтому нужно явно использовать GetModuleFileNameW, ну а с ней см. "во-первых" — короче говоря, вся эта возня с удвоением недостаточной ёмкости буфера вряд ли оправдана.
Здравствуйте, Warturtle, Вы писали: W>В-третьих, функция GetModuleFileNameA не может вернуть путь длиннее MAX_PATH, поэтому нужно явно использовать GetModuleFileNameW, ну а с ней см.
А можно отсюда поподробнее, плз? Почему ANSI-версия не может вернуть путь длиннее чем MAX_PATH? Вроде ж там можно задать размер буфера равный СКОЛЬКО_ХОЧУ? Почему тогда ANSI-версия в принципе (я так понимаю) не может вернуть путь длиньше MAX_PATH?
Здравствуйте, Carc, Вы писали:
C>А можно отсюда поподробнее, плз? Почему ANSI-версия не может вернуть путь длиннее чем MAX_PATH? Вроде ж там можно задать размер буфера равный СКОЛЬКО_ХОЧУ? Почему тогда ANSI-версия в принципе (я так понимаю) не может вернуть путь длиньше MAX_PATH?
Эксперимента ради. Win 10. Вот что самое длинное у меня получилось создать:
D:\1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\123456789012345678901234567890123456789012\1234567.txt
Дальше система ругается, мол слишком длинно — не пойдет.
Итого: 3 + 100 + 1 + 100 + 1 + 42 + 1 + 7 + 4 = 259, а MAX_PATH = 260 (на нолик в конце заложились)
Хотелось бы конечно документально об этом прочитать.
Здравствуйте, dosik, Вы писали:
D>Здравствуйте, Carc, Вы писали:
D>Эксперимента ради. Win 10. Вот что самое длинное у меня получилось создать: D>D:\1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\123456789012345678901234567890123456789012\1234567.txt D>Дальше система ругается, мол слишком длинно — не пойдет. D>Итого: 3 + 100 + 1 + 100 + 1 + 42 + 1 + 7 + 4 = 259, а MAX_PATH = 260 (на нолик в конце заложились) D>Хотелось бы конечно документально об этом прочитать.
И я про тоже. В доке про это ограничение вроде ни слова!?!
Здравствуйте, Carc, Вы писали:
C>Здравствуйте, Warturtle, Вы писали: W>>В-третьих, функция GetModuleFileNameA не может вернуть путь длиннее MAX_PATH, поэтому нужно явно использовать GetModuleFileNameW, ну а с ней см.
C>А можно отсюда поподробнее, плз? Почему ANSI-версия не может вернуть путь длиннее чем MAX_PATH? Вроде ж там можно задать размер буфера равный СКОЛЬКО_ХОЧУ? Почему тогда ANSI-версия в принципе (я так понимаю) не может вернуть путь длиньше MAX_PATH?
Может быть я ошибаюсь, но обычно ансишные версии функций, работающие с путями ограничены длиной MAX_PATH. Для интереса попытался запустить (на Win7) exe-файл с полным именем >> MAX_PATH (на самом деле там возможно 'БукваДиска:\<MAX_PATH>') и ничего не вышло: эксплорер ругается на настройки безопасности, а CreateProcessW возвращает "The system cannot find the path specified." (GetLastError() == 3). Так что в практическом плане все еще проще.
P.S. Про ограничения в длине путей для ансишных версий и как их обходить (в юникодных версиях функций) написано в статье Naming a File.
Здравствуйте, Warturtle, Вы писали:
W>Здравствуйте, Carc, Вы писали:
C>>Здравствуйте, Warturtle, Вы писали: W>>>В-третьих, функция GetModuleFileNameA не может вернуть путь длиннее MAX_PATH, поэтому нужно явно использовать GetModuleFileNameW, ну а с ней см.
C>>А можно отсюда поподробнее, плз? Почему ANSI-версия не может вернуть путь длиннее чем MAX_PATH? Вроде ж там можно задать размер буфера равный СКОЛЬКО_ХОЧУ? Почему тогда ANSI-версия в принципе (я так понимаю) не может вернуть путь длиньше MAX_PATH? W>Может быть я ошибаюсь, но обычно ансишные версии функций, работающие с путями ограничены длиной MAX_PATH. Для интереса попытался запустить (на Win7) exe-файл с полным именем >> MAX_PATH (на самом деле там возможно 'БукваДиска:\<MAX_PATH>') и ничего не вышло: эксплорер ругается на настройки безопасности, а CreateProcessW возвращает "The system cannot find the path specified." (GetLastError() == 3)...
По короткому имени (8.3) такой исполняемый файл запустить можно, если суммарная длина пути, опять же, не превышает 260, но тогда и GetModuleFileName, вызванная из него, вернет короткий вариант пути.
Здравствуйте, Warturtle, Вы писали:
W>Здравствуйте, Carc, Вы писали:
C>>Здравствуйте, Warturtle, Вы писали: W>>>В-третьих, функция GetModuleFileNameA не может вернуть путь длиннее MAX_PATH, поэтому нужно явно использовать GetModuleFileNameW, ну а с ней см.
C>> CreateProcessW возвращает "The system cannot find the path specified." (GetLastError() == 3). Так что в практическом плане все еще проще.
Должно работать с длинными путями "\\?.." и только в 64-битном приложении под 64-битной виндой
D>По уму в строках память должна выделяться непрерывно, но вот может ли это измениться?
вам стоит понять, что строки стл как впрочем и многие другие классы были созданы академиками и для реального программирования пригодны чуть менее, чем никак.
Это не более, чем абстрактные строки в вакууме, с которыми ничего нельзя делать, только сидеть и радоваться, что они есть.
Z>вам стоит понять, что строки стл как впрочем и многие другие классы были созданы академиками и для реального программирования пригодны чуть менее, чуть никак. Z>Это не более, чем абстрактные строки в вакууме, с которыми ничего нельзя делать, только сидеть и радоваться, что они есть.
А попробуйте создать свой собственный класс строк. А вот потом поиграться с ним в плане переносимости кода Вот тогда и вспомните про академизм
Здравствуйте, Zenden, Вы писали:
Z>Здравствуйте, Warturtle, Вы писали:
W>>Здравствуйте, Carc, Вы писали:
C>>>Здравствуйте, Warturtle, Вы писали: W>>>>В-третьих, функция GetModuleFileNameA не может вернуть путь длиннее MAX_PATH, поэтому нужно явно использовать GetModuleFileNameW, ну а с ней см.
C>>> CreateProcessW возвращает "The system cannot find the path specified." (GetLastError() == 3). Так что в практическом плане все еще проще.
Z>Должно работать с длинными путями "\\?.." и только в 64-битном приложении под 64-битной виндой
Ну если только 64-битное. Я пробовал и с "\\?\", и с коротким (просто именем exe-файла из папки с ним): там вообще забавно было — CreateProcessW возвращал ошибку, а GetLastError() == ERROR_SUCCESS.