c++ - 如何让“工厂函数”返回不可复制的对象?
问题描述
语境
尝试在内部创建一些具有不同文件名的 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;
}
问题
这(如我们所料)会产生核心转储,因为makeGZipStream
我们尝试通过(右值)引用返回本地堆栈分配的变量。但是在这种情况下,副本不是一个选项,因为boost::iostreams::filtering_ostream
它是不可复制的。
问题
- 由于它的移动构造函数,我们可以返回一个
std::unique_ptr
“按值”(由于复制省略,移动甚至不应该在 C++17 中发生),为什么在这种情况下不可能呢? - 那里有什么好的解决方案?
可能的解决方案
- 将所有内容放在同一范围内(我试图避免的)
- 将您的对象包装在一个
unique_ptr
(不太漂亮)中 - 还要别的吗 ?
笔记
使用的编译器是相当旧的g++ (GCC) 4.9.3
.
解决方案
只需按值返回并std::move()
从返回语句中删除:
boost::iostreams::filtering_ostream makeGZipStream(const std::string& archiveName,
const std::string& fileName)
{
...
return theGzipStream;
}
如果由于缺少移动构造函数而无法编译,那么您很不走运并且这种类型不可移动,因此将其包装std::unique_ptr
并按值返回该指针(这肯定是可移动的)。
推荐阅读
- javascript - 对值求和,并将具有相同 id 的对象值合并到一个新数组中
- python - 我应该使用一个类在函数之间共享多个变量吗?
- c# - Select-Tag Helper .NET Core 到控制器
- java - 为什么我的 Java 应用程序在启动后随机冻结?
- css - 带有浮动的 CSS 网格,如果设置宽度的类不是第一个,则不起作用
- javascript - forEach 代码不起作用,但是两个不同的 forEach 函数中的相同代码可以,为什么?
- python - 如何在具有优先键的两个键上加入熊猫数据框?
- wordpress - 如何使用 Alexa 技能从 WordPress 制作的网站中获取内容?
- ajax - 如何检查ajax resonse是对象还是简单字符串
- c++ - 使用 std::reference_wrapper
在构造函数中处理 const T& - 合适吗?