为什么使用引用成员可以防止已删除的构造函数错误?

Why does using a reference member prevent deleted constructor errors?

提问人:kymkcay 提问时间:4/25/2021 更新时间:4/25/2021 访问量:121

问:

上下文

我有两个类(简化为相关声明):

#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]'

在最终发现一个类不存在默认构造函数的错误之后,我想我现在明白了:

  • 问题是它有一个删除的默认构造函数,它阻止被使用,因为它没有被提供字符串(而类本身编译良好)。ifstreamLexerParserLexer
  • 如果我直接做一个,仍然有一个错误(与上面类似的推理),因为它也有一个已删除的复制构造函数。Lexerifstream
  • 通过创建引用成员(即 ),解决了缺少复制构造函数的问题,因为成员初始化器不再尝试使用复制构造函数(因为它只是一个引用)。file_std::ifstream &file_;

我的问题是:

  1. 我的理解正确吗?感觉有点模糊,但我是 C++ 的新手,仍然习惯于思考在不同上下文中使用引用(我理解一般概念)。
  2. 为什么这里缺少默认构造函数是一个问题,而当只声明类(如上所述)时却不是?Lexer
  3. 在这里,使用引用成员是语义上最正确的解决方案吗?
C++ 引用 复制构造函数 default-constructor

评论

0赞 πάντα ῥεῖ 4/25/2021
因为引用不需要复制构造?
2赞 M.M 4/25/2021
不可复制的事实意味着不可复制ifstreamLexer
0赞 Peter 4/25/2021
复制 需要复制包含的 OBJECT。不允许复制(因为从逻辑上讲,这意味着两个不同对象的最终结果,每个对象都管理来自同一物理文件的不同数据流)。Lexerifstreamifstream

答:

3赞 ChrisMM 4/25/2021 #1

ifstream确实有一个默认构造函数。由于删除了复制构造函数而粘贴它的错误。你写的代码是行不通的,因为不能用默认的复制构造,因为是不可复制的。Lexerifstream

所以,为了回答你的问题:

  1. 你的理解是不正确的;虽然不是一个糟糕的猜测。
  2. 与默认构造函数无关。
  3. 取决于你要做什么。您可能希望阻止 Lexer 的复制,或创建自己的复制构造函数,或使用引用。

评论

0赞 kymkcay 4/25/2021
谢谢,这很好地回答了我的问题,我想我真正的困惑来源是什么(它只是为我点击了隐式复制构造函数也必须复制构造成员)。知道缺少复制构造函数是问题所在,这也解释了为什么它只有在解析器中使用后才成为问题。