4

这是我的 C++ 代码的一个片段:

std::queue<std::string> get_file_names(const std::string &indir)
{
    std::queue<std::string> file_names;

    fs::recursive_directory_iterator end;
    for (fs::recursive_directory_iterator it(indir); it != end; it++) {
        const std::string &extn = it->path().extension().string();
        if (extn == ".zip") {
            const std::string &file_name = it->path().string();
            file_names.push(file_name);
        }
    }

    return file_names;
}

使您不会修改 const 引用的每个字符串都是一个好习惯吗?我很难理解在这种情况下如何存在这样的参考。就像上面的返回值it->path().string()。当推回向量时,如何将它分配给以后可以在函数范围之外使用的引用?

我觉得它必须与std::move.

4

3 回答 3

4

你的代码:

const std::string &file_name = it->path().string();

延长std::stringstd::filesystem::path::string(). 由于您已将其标记为const,因此无法将其移入file_names,因此必须将其复制。假设你想搬家,你会写:

auto&& file_name = // ...
file_names.push(std::move(file_name));

请注意,它std::queue具有push()r 值引用的重载。

现代 C++ 为编译器提供了很多优化机会,因此避免关于悬空引用的问题/“混淆”(auto&&C++11 中的语法是“新的”)可能是更好的方法:

auto file_name = // ...
file_names.push(std::move(file_name));

编写“看起来和行为都像ints”的“自然”代码通常是一个好方法。在不太可能的情况下你发现这确实是一个性能瓶颈,你可以重新审视;为了清楚起见,首先编写代码。

于 2021-04-03T15:42:38.830 回答
2

不,我不建议使用const std::string&. 如果您想让查看器查看字符串,请std::string_view改用。std::string_view不仅适用于旧的 C 风格 API,其中函数接受const char*作为输入但没有提交其大小的选项;希望这些 API 最终会消失。所有体面的 API 总是添加提交选项const char*及其大小作为附加选项。

如果您想要一个std::stringthen just usestd::string或者如果您想明确声明您不打算更改它,那么只需 make it const std::string

在您的情况下,正如其他答案所指出的那样,path' 方法返回的对象.string()是一个std::string因此const std::string&明确地捕获它只是没有意义的。

如果您将其存储为std::stringthen 至少您可以将其移动到 outputstd::queue<std::string> file_names中。

编辑:关于为什么旧的 C 风格的字符串不好并且应该转发该长度。请检查这篇文章

https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times-by-70/

结果表明 GTA 的加载时间非常慢(几分钟,平均 5-6 分钟),因为它strlen在读取 10mb json 文件时一遍又一遍地卡住了计算。

于 2021-04-03T16:26:15.683 回答
1

解释

当推回向量时,如何将它分配给以后可以在函数范围之外使用的引用?

变量file_names是类型的std::queue<std::string>(而不是std::queue<std::string&>- 顺便说一句,这种方式不可能,但使用std::reference_wrapper)。所以它不存储“对字符串的引用”,而是存储实际的“字符串”。

如果你推送一个字符串引用,实际上会推送一个被引用字符串的副本。


使您不会修改const 引用的每个字符串都是一个好习惯吗?

关于“最佳实践”,考虑使用std::string_view来换取 const 字符串引用(至少从 C++17 开始)。


我觉得它必须与std::move.

它不是。在这种情况下,它与std::queue.

奖金

您可以使用reference_wrapper作为类型参数将引用存储在 (STL) 容器中。

于 2021-04-03T15:45:34.383 回答