【发布时间】:2021-10-03 15:47:03
【问题描述】:
我有一个将文件读入字符串变量的函数。而且我不确定有什么更好的方法来实现它:
void readFile(const std::filesystem::path& path, std::string& dest)
{
std::ifstream input(path, std::ios::in | std::ios::binary);
if (!input.is_open())
{
// throw exception
}
const std::size_t size = std::filesystem::file_size(path);
std::string().swap(dest);
dest.resize(size);
input.read(&dest[0], size);
input.close();
if (input.fail() && !input.eof())
{
// throw exception
}
}
或者:
std::string readFile(const std::filesystem::path& path)
{
std::ifstream input(path, std::ios::in | std::ios::binary);
if (!input.is_open())
{
// throw exception
}
const std::size_t size = std::filesystem::file_size(path);
std::string buffer(size, '\0');
input.read(&buffer[0], size);
input.close();
if (input.fail() && !input.eof())
{
// throw exception
}
return buffer;
}
要读取的文件大小可能是几个字节到几百兆字节,因此读取操作可能非常昂贵。互联网上有很多建议总是更喜欢使用返回值的第二种方法,让编译器进行所需的优化。但是如果效率对我很重要,我可以完全依赖编译器吗?我可以确定编译器总是更喜欢 RVO 而不是要返回的数据的冗余副本吗?
【问题讨论】:
-
首先,这是NRVO,不像RVO不是强制性的。但是即使 NRVO 失败,字符串也会被移动而不是复制,所以你不会丢失任何东西。
-
从技术上讲,如果字符串足够短并且您的实现使用短字符串优化,则会发生副本,但这仍然是我的编码方式。我讨厌使用 out 参数。
-
先写惯用代码,再写profile。过早的优化是万恶之源。
-
@SergeyA 这显然是双曲线的,我的实际建议会更加细微,不适合 StackOverflow 评论。但主要的一点是,在不分析代码的情况下说“我关心性能”是不合逻辑的。
-
@0x5453 没有人说不应该分析代码。然而,编写一个天生缓慢的代码是一种灾难——您将永远无法以后对其进行优化,因为它永远不会被分析器突出显示,因为它是许多小问题。这将是千刀万剐的死亡。人们应该始终知道他们的目标是哪种性能配置文件并相应地编写代码。
标签: c++ return-value-optimization