Re[3]: Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 08.09.15 18:16
Оценка:
Здравствуйте, watchmaker, Вы писали:

Прогнал дебагером интереса ради, действительно в первом случае после конструктора вызывается деструктор, который выполняет delete[].
Думаю что вариант с "умным" указателем даже предпочтительней чем вектор для выделения таких "одноразовых" буферов для API.
Что касается второго случая, то действительно все равно происходит копирование, что-то я тупанул. Перемещать он умеет только строки в строки, все остальное будет копировать.

Спасибо.
Re[3]: Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 09.09.15 07:06
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>
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 и при наличии перемещающего конструктора будет перемещен, а явно указывать это нет необходимости?
Re[2]: Строки - обращение на прямую
От: Warturtle  
Дата: 09.09.15 07:13
Оценка:
Здравствуйте, 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, ну а с ней см. "во-первых" — короче говоря, вся эта возня с удвоением недостаточной ёмкости буфера вряд ли оправдана.
Re[3]: Строки - обращение на прямую
От: Carc Россия https://vk.com/gosha_mazov
Дата: 09.09.15 07:18
Оценка:
Здравствуйте, Warturtle, Вы писали:
W>В-третьих, функция GetModuleFileNameA не может вернуть путь длиннее MAX_PATH, поэтому нужно явно использовать GetModuleFileNameW, ну а с ней см.

А можно отсюда поподробнее, плз? Почему ANSI-версия не может вернуть путь длиннее чем MAX_PATH? Вроде ж там можно задать размер буфера равный СКОЛЬКО_ХОЧУ? Почему тогда ANSI-версия в принципе (я так понимаю) не может вернуть путь длиньше MAX_PATH?
Aml Pages Home
Re[4]: Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 09.09.15 07:39
Оценка:
Здравствуйте, 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 (на нолик в конце заложились)
Хотелось бы конечно документально об этом прочитать.
Re[5]: Строки - обращение на прямую
От: Carc Россия https://vk.com/gosha_mazov
Дата: 09.09.15 08:29
Оценка:
Здравствуйте, 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>Хотелось бы конечно документально об этом прочитать.
И я про тоже. В доке про это ограничение вроде ни слова!?!
Aml Pages Home
Re[4]: Строки - обращение на прямую
От: Warturtle  
Дата: 09.09.15 08:34
Оценка: 1 (1)
Здравствуйте, 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.
Re[6]: Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 09.09.15 08:37
Оценка:
Здравствуйте, Carc, Вы писали:

C>И я про тоже. В доке про это ограничение вроде ни слова!?!

Ну плюс — минус: https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
Re[5]: Строки - обращение на прямую
От: Warturtle  
Дата: 09.09.15 08:42
Оценка:
Здравствуйте, 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, вызванная из него, вернет короткий вариант пути.
Re[2]: Строки - обращение на прямую
От: B0FEE664  
Дата: 09.09.15 08:49
Оценка:
Здравствуйте, dosik, Вы писали:

D>
D>    string path(std::move(&buff[0]));                //Действительно ли это будет оптимальней, нежели string path(&buff[0])
D>

Оптимальней будет так:
  assert(0 <= mfn_size);
  string path(&buff[0], &buff[mfn_size]);
И каждый день — без права на ошибку...
Re[3]: Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 09.09.15 09:01
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Оптимальней будет так:

BFE>
BFE>  assert(0 <= mfn_size);
BFE>  string path(&buff[0], &buff[mfn_size]);
BFE>

А почему не:
    string path(&buff[0], mfn_size);

???
Re[4]: Строки - обращение на прямую
От: B0FEE664  
Дата: 09.09.15 09:19
Оценка:
Здравствуйте, dosik, Вы писали:

BFE>>Оптимальней будет так:

BFE>>
BFE>>  assert(0 <= mfn_size);
BFE>>  string path(&buff[0], &buff[mfn_size]);
BFE>>

D>А почему не:
D>
D>    string path(&buff[0], mfn_size);
D>

D>???

Так тоже можно.
И каждый день — без права на ошибку...
Re[5]: Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 09.09.15 09:20
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Так тоже можно.


В общем то смысл — избавить от вычисления длинны строки?
Re[6]: Строки - обращение на прямую
От: B0FEE664  
Дата: 09.09.15 09:36
Оценка:
Здравствуйте, dosik, Вы писали:

D>В общем то смысл — избавить от вычисления длинны строки?


да.
И каждый день — без права на ошибку...
Re[5]: Строки - обращение на прямую
От: Zenden Россия  
Дата: 09.09.15 14:48
Оценка:
Здравствуйте, Warturtle, Вы писали:

W>Здравствуйте, Carc, Вы писали:


C>>Здравствуйте, Warturtle, Вы писали:

W>>>В-третьих, функция GetModuleFileNameA не может вернуть путь длиннее MAX_PATH, поэтому нужно явно использовать GetModuleFileNameW, ну а с ней см.

C>> CreateProcessW возвращает "The system cannot find the path specified." (GetLastError() == 3). Так что в практическом плане все еще проще.


Должно работать с длинными путями "\\?.." и только в 64-битном приложении под 64-битной виндой
Re: Строки - обращение на прямую
От: Zenden Россия  
Дата: 09.09.15 14:50
Оценка: -3 :))
Здравствуйте, dosik, Вы писали:

D>Интересно, на сколько допустимо лезть на прямую в память строк, например:

D>
D>    std::string mfn(MAX_PATH, 0);
D>    DWORD size = GetModuleFileName(NULL, &mfn[0], mfn.size());
D>

D>По уму в строках память должна выделяться непрерывно, но вот может ли это измениться?

вам стоит понять, что строки стл как впрочем и многие другие классы были созданы академиками и для реального программирования пригодны чуть менее, чем никак.
Это не более, чем абстрактные строки в вакууме, с которыми ничего нельзя делать, только сидеть и радоваться, что они есть.
Отредактировано 09.09.2015 15:29 Zenden . Предыдущая версия .
Re[2]: Строки - обращение на прямую
От: Carc Россия https://vk.com/gosha_mazov
Дата: 09.09.15 15:09
Оценка:
Z>вам стоит понять, что строки стл как впрочем и многие другие классы были созданы академиками и для реального программирования пригодны чуть менее, чуть никак.
Z>Это не более, чем абстрактные строки в вакууме, с которыми ничего нельзя делать, только сидеть и радоваться, что они есть.
А попробуйте создать свой собственный класс строк. А вот потом поиграться с ним в плане переносимости кода Вот тогда и вспомните про академизм
Aml Pages Home
Re[6]: Строки - обращение на прямую
От: Warturtle  
Дата: 09.09.15 15:20
Оценка:
Здравствуйте, 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.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.