我正在尝试从构造函数初始化std :: ifstream引用,但是我收到错误说
invalid initialization of reference of type ‘std::ifstream& {aka std::basic_ifstream<char>&}’ from expression of type ‘const string {aka const std::__cxx11::basic_string<char>}’
A(const std::string& file_name):inFile(file_name){}
以下是代码
#include <string>
#include <fstream>
class A{
public:
A(const std::string& file_name):inFile(file_name){}
private:
std::ifstream& inFile;
};
int main(){
A("text.txt");
}
答案 0 :(得分:6)
在
class A{
public:
A(const std::string& file_name):inFile(file_name){}
private:
std::ifstream& inFile;
};
必须初始化 inFile
以引用现有的istream
。 inFile(file_name)
不会构建istream
;它会尝试inFile
引用string
。编译器无法正常工作并发出错误。
上述说明
inFile
不是ifstream
。 It is a reference,一个别名,变量为ifstream
的变量。您无法构建引用,因为没有任何内容可以构造。它只是已存在的变量的新名称。必须构造引用的变量。
为什么这适用于int
如果你
class A{
public:
A(int & an_Int):int_Ref(an_Int){}
private:
int & int_Ref;
};
int_Ref
是指int
所指的an_Int
。如果相反,你
A(int an_int):int_Ref(an_int){}
它仍然会编译,但是你有一个问题因为int_Ref
引用an_int
,这是一个作用于构造函数的自动变量。当你使用an_int
进行任何操作时,A
已经死了,可能会被埋葬。使用int_Ref
将是Undefined Behaviour,并且由于行为未定义,所以可能发生任何事情,包括您期望的行为。在蚱蜢打喷嚏并且程序突然停止正常工作之前,这可能会让你长时间愚弄。事实上,从未正常工作。
A(const std::string& file_name):intRef(file_name){}
由于int
引用无法引用std::string
,因此无法正常工作。
有两个合理的选择:
选项1
class A{
public:
A(const std::string& file_name):inFile(file_name){}
private:
std::ifstream inFile; // no longer a reference
};
将在istream
的实例中为指定文件构建A
。
选项2
class A{
public:
A(std::ifstream & in):inFile(in){} // accepts ifstream reference, not string reference
private:
std::ifstream & inFile;
};
初始化inFile
以引用ifstream
引用的给定预先存在的in
。这意味着
int main(){
A("text.txt");
}
必须成为
int main(){
std::ifstream in("text.txt");
A(in);
}
需要注意的是,提供给ifstream
的{{1}}的生命周期必须大于A
实例的生命周期。这意味着
A
是一个死亡陷阱。返回的A ABuilder(const std::string& file_name)
{
std::ifstream in(file_name);
return A(in);
}
包含对不再存在的对象的引用。
由于选项2出错的可能性增加,我建议更喜欢选项1