【发布时间】:2018-12-28 22:03:27
【问题描述】:
上下文
尝试在其中创建一些具有不同文件名的 gzip 存档,我在以下 sn-p 代码中编写了此代码。
#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;
}
问题
这(如我们所料)会产生核心转储,因为在makeGZipStream 中,我们尝试通过(右值)引用返回本地堆栈分配的变量。但在这种情况下,副本不是一个选项,因为boost::iostreams::filtering_ostream 是不可复制的。
问题
- 我们可以 return a
std::unique_ptr"by value" 感谢它的移动构造函数(由于复制省略,移动甚至不应该在 C++17 中发生),为什么在这种情况下不可能? - 那里有什么好的解决方案?
可能的解决方案
- 将所有内容放在同一个范围内(我试图避免的)
- 将对象包装在
unique_ptr中(不太漂亮) - 还有别的吗?
注意事项
使用的编译器是相当老的g++ (GCC) 4.9.3。
【问题讨论】:
-
@SergeyA 是的,问题中已经提到了。
-
@matovitch 如果您使用
return std::move(theGzipStream);并且它仍然报错,请确保您的类型具有移动构造函数。 -
@matovitch 您的问题实际上是不正确的。它适用于
unique_ptrs 不是因为复制省略,而是因为移动构造函数 -
@matovitch 那么您的类型既不可复制又不可移动。它永远不能按值返回。最简单的解决方法可能是将其包装在
unique_ptr中。 -
@matovitch,没关系,它在语义上仍然相同。如果没有移动构造函数,
unique_ptr将无法从函数返回(不包括 C++ 17 复制省略)。
标签: c++ c++11 move-semantics copy-elision noncopyable