mat*_*tch 1 c++ noncopyable move-semantics copy-elision c++11
尝试使用不同的文件名创建一些gzip存档我写下以下代码片段.
#include <iostream>
#include <utility>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filter/gzip.hpp>
boost::iostreams::filtering_ostream&& makeGZipStream(const std::string& archiveName,
const std::string& fileName)
{
boost::iostreams::filtering_ostream theGzipStream;
boost::iostreams::gzip_params theGzipParams;
theGzipParams.file_name = fileName;
theGzipStream.push(boost::iostreams::gzip_compressor{theGzipParams});
theGzipStream.push(boost::iostreams::file_sink{archiveName});
return std::move(theGzipStream);
}
int main()
{
boost::iostreams::filtering_ostream&& theGzipStream = makeGZipStream("archive.gz", "file");
theGzipStream << "This is a test..." << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这(我们可以预期)会产生核心转储,因为makeGZipStream我们尝试通过(rvalue-)引用返回本地堆栈分配的变量.但在这种情况下,副本不是一个选项,因为它boost::iostreams::filtering_ostream是不可复制的.
std::unique_ptr"按值"(由于copy-elision,这个移动甚至不应该出现在C++ 17中),为什么在这种情况下不可能呢?unique_ptr(不那么漂亮)使用的编译器很老了g++ (GCC) 4.9.3.
只需按值返回并std::move()从return语句中删除:
boost::iostreams::filtering_ostream makeGZipStream(const std::string& archiveName,
const std::string& fileName)
{
...
return theGzipStream;
}
Run Code Online (Sandbox Code Playgroud)
如果由于缺少移动构造函数而无法编译,那么你运气不好并且这种类型不可移动,所以将其包装std::unique_ptr并按值返回该指针(可以肯定是可移动的).