为什么使用引用成员可以防止删除的构造函数错误?
Why does using a reference member prevent deleted constructor errors?
上下文
我有两个classes(简化为相关声明):
#include <string>
#include <fstream>
class Lexer
{
std::ifstream file_;
Lexer(std::string &file) : file_(file){};
};
class Parser
{
Lexer lexer_;
Parser(Lexer &lex) : lexer_(lex){};
};
编译失败,出现错误
error: use of deleted function 'std::basic_ifstream<_CharT, _Traits>::basic_ifstream(const std::basic_ifstream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits]'
最终找到 我想我现在明白了:
- 问题是
ifstream
有一个删除的默认构造函数,它阻止 Lexer
在 Parser
中使用,因为它没有被提供一个字符串(而 Lexer
class 本身编译良好)。
- 如果我让
Lexer
直接取一个 ifstream
仍然有一个错误(与上面类似的推理),因为它也有一个删除的复制构造函数。
- 通过使
file_
成为引用成员(即 std::ifstream &file_;
),缺少复制构造函数的问题得到解决,因为成员初始化程序不再尝试使用复制构造函数(因为它只是一个引用).
我的问题是:
- 我的理解对吗?感觉有点模糊,但我是C++的新手,还在习惯思考在不同上下文中引用的使用(我理解一般概念)。
- 为什么这里缺少默认构造函数确实是一个问题,而当仅声明
Lexer
class(如上所述)时却不是?
- 这里使用引用成员是语义上最正确的解决方案吗?
ifstream
确实有默认构造函数。由于删除了复制构造函数,您粘贴它的错误。你写的代码是行不通的,因为Lexer
不能用默认的复制构造,因为ifstream
是不可复制的。
所以,回答你的问题:
- 您的理解有误;虽然猜得不错。
- 与默认构造函数无关。
- 取决于您要做什么。你可能想阻止 Lexer 的复制,或者创建你自己的复制构造函数,或者使用引用。
上下文
我有两个classes(简化为相关声明):
#include <string>
#include <fstream>
class Lexer
{
std::ifstream file_;
Lexer(std::string &file) : file_(file){};
};
class Parser
{
Lexer lexer_;
Parser(Lexer &lex) : lexer_(lex){};
};
编译失败,出现错误
error: use of deleted function 'std::basic_ifstream<_CharT, _Traits>::basic_ifstream(const std::basic_ifstream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits]'
最终找到
- 问题是
ifstream
有一个删除的默认构造函数,它阻止Lexer
在Parser
中使用,因为它没有被提供一个字符串(而Lexer
class 本身编译良好)。 - 如果我让
Lexer
直接取一个ifstream
仍然有一个错误(与上面类似的推理),因为它也有一个删除的复制构造函数。 - 通过使
file_
成为引用成员(即std::ifstream &file_;
),缺少复制构造函数的问题得到解决,因为成员初始化程序不再尝试使用复制构造函数(因为它只是一个引用).
我的问题是:
- 我的理解对吗?感觉有点模糊,但我是C++的新手,还在习惯思考在不同上下文中引用的使用(我理解一般概念)。
- 为什么这里缺少默认构造函数确实是一个问题,而当仅声明
Lexer
class(如上所述)时却不是? - 这里使用引用成员是语义上最正确的解决方案吗?
ifstream
确实有默认构造函数。由于删除了复制构造函数,您粘贴它的错误。你写的代码是行不通的,因为Lexer
不能用默认的复制构造,因为ifstream
是不可复制的。
所以,回答你的问题:
- 您的理解有误;虽然猜得不错。
- 与默认构造函数无关。
- 取决于您要做什么。你可能想阻止 Lexer 的复制,或者创建你自己的复制构造函数,或者使用引用。