我可以始终依赖编译器的 RVO 吗?

Can I always rely on RVO by the compiler?

我有一个将文件读入字符串变量的函数。而且我不确定什么是更好的实现方式:


            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, '[=11=]');
                input.read(&buffer[0], size);
                input.close();
                if (input.fail() && !input.eof())
                {
                    // throw exception
                }
                return buffer;
            }

要读取的文件大小可能是几个字节到几百兆字节,因此读取操作可能会非常昂贵。 Internet 上有很多建议总是更喜欢使用 return 值的第二种方法,只让编译器进行所需的优化。但是,如果效率对我很重要,我能完全依赖编译器吗?我可以确定编译器总是更喜欢 RVO 而不是要 returned 的数据的冗余副本吗?

正如其他人所提到的,不能保证编译器会对此进行优化,因为 returned 值是一个命名变量(参见 https://en.cppreference.com/w/cpp/language/copy_elision)。

但是,在我看来,如果启用优化,您几乎总是可以依赖 RVO,因为 RVO 是编译器可以执行的第一个也是最简单的优化之一。原因是,在底层架构中,没有办法直接 return 一个大值(比 CPU 寄存器大)。它的实现方式是调用者函数将为 return 值分配一个局部变量,并将指向此的指针传递给被调用者。如此有效,编译器已经在堆栈上分配了一个局部变量,并且将使用这个而不是分配另一个相同的变量。编译器将直接在调用函数局部变量中就地构造您的字符串。