如果 iostream 对象不可复制,为什么以下代码是合法的?
If iostream objects are not copyable, why is the following code legal?
我一直在读"C++入门",在第8章中我们讨论了I/O。声明无法复制或分配 I/O 对象。如果是这样,那么为什么下面的代码要编译并运行呢?
std::ifstream get_lines(const std::string &fname, std::vector<std::string> &v)
{
std::ifstream file(fname);
if (!file) {
std::cerr << "Error opening file: " << fname << std::endl;
return file;
}
std::string buf;
while (std::getline(file, buf))
v.push_back(buf);
return file;
}
int main()
{
std::vector<std::string> v;
auto f = get_lines("test.txt", v);
f.close();
return 0;
}
返回不会创建随后用于初始化f
的file
副本吗?
请参阅此页面。当你说
return file;
file
是一个"id-expression"(即它是某个变量的名称(。这些在return
下有特殊处理:
自动从局部变量和参数移动
如果表达式是一个(可能是括号(命名变量的 id 表达式......然后重载解析以选择要用于初始化返回值的构造函数...执行两次:
- 首先,好像表达式是右值表达式(因此它可以选择移动构造函数(,...
- 然后像往常一样执行重载解析,将表达式视为左值(因此它可以选择复制构造函数(。
你不能复制ifstream
,这是真的,但你可以移动它。因此,编译器实质上为您插入了一个隐式std::move
:
return std::move(file);
这允许调用ifstream
的移动构造函数,即使复制构造函数被删除也是如此。"移动"意味着istream
"拥有"的任何资源都转移到新对象。移动构造函数将这些资源的所有权从源对象手中夺走(从而对其进行修改(,同时将其提供给新对象。对比复制构造函数,我们通常认为它不应该修改源代码,因此不能剥夺它的所有权。这使得复制构造函数对istream
不安全,因为这意味着两个对象试图管理一个外部资源并可能相互混淆。移动构造函数不受协定的约束,使源对象保持不变,因此它可以确保资源仅由一个对象拥有。
相关文章:
- 为什么我们不在下面给出的代码中使用指针来实例化C++的实体对象?
- 如果 iostream 对象不可复制,为什么以下代码是合法的?
- 使用 gtest 框架在单元测试代码中检查目标对象的私有变量的最佳实践是什么?
- 创建跨平台 C++ 触摸管理器.在 c++ 中传递 Objective-c 对象涉及代码
- 由于缺少类模板,NVCC 编译面向对象代码时出现问题
- 使用 jni 将返回带有模板的对象的 Java 代码转换为 c++
- 在 C++ 对象包装器中安全地包含 C 代码
- 在C++代码中搜索对象的实例化位置
- 使用.natvis文件可视化VS代码中的C++对象
- C++指向对象的指针堆数组中,如何将字符串传递给特定对象?有一些代码请看一下:
- C++ 被此代码与多态性、指针和对象切片混淆
- 从本机代码返回到托管代码会损坏返回的对象
- 如果用户尝试从 JS 调用对象的未定义函数C++则回调C++代码
- 在 boost::p ython 中的 python 对象中运行 python 代码
- 初始化不可移动对象数组:为什么这样的代码无法在 GCC 上编译?
- 一般函数中类的概括为基类创建对象代码
- C++模板的对象代码是否在可执行文件和动态库中重复?
- 我不想导出的函数的未记录代码对象警告
- 代码对象和可执行文件的区别
- 如何保持作为 SWIG shared_ptr传递给非托管代码的托管代码对象的活动状态?