1

Тема: Робота з вказівнком const char* від .c_str()

Генерую потрібні мені шляхи до файлів у теці ось так:

    struct stat sb {};

    for (const auto& entry :
         std::filesystem::directory_iterator(path_to_fonts)) {

        const std::filesystem::path& outfilename { entry.path() };
        std::string outfilename_str { outfilename.string() };
        const char* path { outfilename_str.c_str() };

        if (stat(path, &sb) == 0 && !(sb.st_mode & S_IFDIR)) {
            file_paths.emplace_back(path);
        }
    }

Мене цікавить вказівник const char* path.
Як він видаляється? Про це дбає метод c_str()?
Чи по завершенні етапу циклу він видаляється як локальна змінна?
Якби було використано new, то мав би видаляти користувач. А в цьому випадку не зовсім розумію.

2

Re: Робота з вказівнком const char* від .c_str()

Так робити не можна.
c_str, фактично, повертає те саме, що й data(), але це не гарантовано, і точно це значення не буде валідним після знищення outfilename_str в кінці кожної ітерації. c_str() призначено для тимчасового використання у функціях, що потребують нуль-термінованих рядків.
Звісно, якщо file_path містить рядки std::string, то тоді буде створено копії... але тоді нащо c_str() в цьому коді?

Подякували: leofun011

3

Re: Робота з вказівнком const char* від .c_str()

koala написав:

Так робити не можна.
c_str, фактично, повертає те саме, що й data(), але це не гарантовано, і точно це значення не буде валідним після знищення outfilename_str в кінці кожної ітерації. c_str() призначено для тимчасового використання у функціях, що потребують нуль-термінованих рядків.
Звісно, якщо file_path містить рядки std::string, то тоді буде створено копії... але тоді нащо c_str() в цьому коді?

struct stat sb{}; походить з #include <sys/stat.h> і приймає лише const char*.
Пробував замінити на unique_ptr, але не вийшло, видає помилки.

4

Re: Робота з вказівнком const char* від .c_str()

        const std::filesystem::path& outfilename { entry.path() };
        if (stat(path.c_str(), &sb) == 0 && !(sb.st_mode & S_IFDIR)) {
            file_paths.emplace_back(path);
        }

5

Re: Робота з вказівнком const char* від .c_str()

Чекайте, ви ж на S_IFDIR перевіряєте.

if (!entry.is_directory()) {
    file_paths.emplace_back(entry.path());
}
Подякували: Teg Miles1

6

Re: Робота з вказівнком const char* від .c_str()

Але підозрюю, що вам is_regular_file() натомість потрібен. Чи щось схоже, прогляньте документацію.

Подякували: Teg Miles1

7

Re: Робота з вказівнком const char* від .c_str()

koala написав:

Але підозрюю, що вам is_regular_file() натомість потрібен. Чи щось схоже, прогляньте документацію.

Ось так вийшло (is_directory() теж підійде, якщо із запереченням):

    for (const auto& entry :
         std::filesystem::directory_iterator(path_to_fonts)) {

        if (entry.is_regular_file()) {
            file_paths.emplace_back(
                std::make_unique<std::string>(entry.path()));
        }
    }

8

Re: Робота з вказівнком const char* від .c_str()

А що саме заважає вам зберігати в file_paths, власне, path?

Подякували: leofun011

9

Re: Робота з вказівнком const char* від .c_str()

koala написав:

А що саме заважає вам зберігати в file_paths, власне, path?

Не зрозумів питання, я більше не створюю проміжної змінної path,
а відразу додаю до вектора вказівник на entry.path().

10

Re: Робота з вказівнком const char* від .c_str()

std::vector<std::filesystem::path> file_paths;
Подякували: Teg Miles, koala, leofun013

11

Re: Робота з вказівнком const char* від .c_str()

Teg Miles написав:
koala написав:

А що саме заважає вам зберігати в file_paths, власне, path?

Не зрозумів питання, я більше не створюю проміжної змінної path,
а відразу додаю до вектора вказівник на entry.path().

З вашою наполегливістю точно треба вивчити Rust. Він вас швидко відучить такі дурниці робити.

Подякували: leofun011

12

Re: Робота з вказівнком const char* від .c_str()

koala написав:
Teg Miles написав:
koala написав:

А що саме заважає вам зберігати в file_paths, власне, path?

Не зрозумів питання, я більше не створюю проміжної змінної path,
а відразу додаю до вектора вказівник на entry.path().

З вашою наполегливістю точно треба вивчити Rust. Він вас швидко відучить такі дурниці робити.

Не варто створювати вказівник на entry.path() і повернути проміжну змінну? Чому?

13

Re: Робота з вказівнком const char* від .c_str()

Teg Miles написав:

Чому?

На це питання я вже відповів у першому ж коментарі. Ну.

Подякували: Teg Miles1

14

Re: Робота з вказівнком const char* від .c_str()

koala написав:
Teg Miles написав:

Чому?

На це питання я вже відповів у першому ж коментарі. Ну.

Точно. Ось так змінив:

auto Fileloader::download_file_paths() -> std::vector<file_path_ptr>
{
    // Завантаження шляхів до файлів шрифтів формату .ttf
    std::vector<file_path_ptr> file_paths;
    const std::string& ttf_extension { ".ttf" };
    for (const auto& entry : std::filesystem::directory_iterator(*main_path)) {
        if (entry.is_regular_file()
            && entry.path().extension() == ttf_extension) {
            const auto& new_path = entry.path();
            file_paths.emplace_back(
                std::make_unique<std::filesystem::path>(new_path));
        }
    }
    return file_paths;
}

Чи прибрати посилання і зробити звичайну копію через move до new_path?

15

Re: Робота з вказівнком const char* від .c_str()

Усе ж таки переробив на звичайну копію:

auto Fileloader::download_file_paths() -> std::vector<file_path_ptr>
{
    // Завантаження шляхів до файлів шрифтів формату .ttf
    std::vector<file_path_ptr> file_paths;
    const std::string& ttf_extension { ".ttf" };
    for (const auto& entry :
         std::filesystem::directory_iterator(*this->main_path)) {
        if (entry.is_regular_file()
            && entry.path().extension() == ttf_extension) {
            std::filesystem::path new_path { entry.path() };
            file_paths.emplace_back(
                std::make_unique<std::filesystem::path>(new_path));
        }
    }
    return file_paths;
}

Питання: Результати виводу методів на зразок .c_str() чи .path() завжди треба копіювати
при збереженні задля уникнення undefined behavior?

16

Re: Робота з вказівнком const char* від .c_str()

Покажчики на щось показують.
Посилання на щось посилаються.
Якщо ви знаєте, де це щось зберігається, і певні, що воно там і буде, поки ви використовуєте покажчики і посилання - можете їх використовувати. Наприклад, якщо вам передали їх аргументом у функцію, то до виходу з функції вони нікуди не подінуться (ну, хіба що ви навмисно їх видалите у функції).
Якщо ж ви не певні - краще скопіюйте кудись собі.

Подякували: Teg Miles1