提问人:kymkcay 提问时间:4/25/2021 更新时间:4/25/2021 访问量:121
为什么使用引用成员可以防止已删除的构造函数错误?
Why does using a reference member prevent deleted constructor errors?
问:
上下文
我有两个类(简化为相关声明):
#include <string>
#include <fstream>
class Lexer
{
std::ifstream file_;
Lexer(std::string &file) : file_(file){};
};
class Parser
{
Lexer lexer_;
Parser(Lexer &lex) : lexer_(lex){};
};
这无法编译并出现错误
错误:使用已删除的函数“std::basic_ifstream<_CharT, _Traits>::basic_ifstream(const std::basic_ifstream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits]'
在最终发现一个类不存在默认构造函数的错误之后,我想我现在明白了:
- 问题是它有一个删除的默认构造函数,它阻止被使用,因为它没有被提供字符串(而类本身编译良好)。
ifstream
Lexer
Parser
Lexer
- 如果我直接做一个,仍然有一个错误(与上面类似的推理),因为它也有一个已删除的复制构造函数。
Lexer
ifstream
- 通过创建引用成员(即 ),解决了缺少复制构造函数的问题,因为成员初始化器不再尝试使用复制构造函数(因为它只是一个引用)。
file_
std::ifstream &file_;
我的问题是:
- 我的理解正确吗?感觉有点模糊,但我是 C++ 的新手,仍然习惯于思考在不同上下文中使用引用(我理解一般概念)。
- 为什么这里缺少默认构造函数是一个问题,而当只声明类(如上所述)时却不是?
Lexer
- 在这里,使用引用成员是语义上最正确的解决方案吗?
答:
3赞
ChrisMM
4/25/2021
#1
ifstream
确实有一个默认构造函数。由于删除了复制构造函数而粘贴它的错误。你写的代码是行不通的,因为不能用默认的复制构造,因为是不可复制的。Lexer
ifstream
所以,为了回答你的问题:
- 你的理解是不正确的;虽然不是一个糟糕的猜测。
- 与默认构造函数无关。
- 取决于你要做什么。您可能希望阻止 Lexer 的复制,或创建自己的复制构造函数,或使用引用。
评论
0赞
kymkcay
4/25/2021
谢谢,这很好地回答了我的问题,我想我真正的困惑来源是什么(它只是为我点击了隐式复制构造函数也必须复制构造成员)。知道缺少复制构造函数是问题所在,这也解释了为什么它只有在解析器中使用后才成为问题。
评论
ifstream
Lexer
Lexer
ifstream
ifstream