Reputation: 4076
The error:
error: invalid initialization of non-const reference of type ‘std::istream& {aka std::basic_istream<char>&}’ from an rvalue of type ‘std::ifstream {aka std::basic_ifstream<char>}’
the code:
class MyClass {
private:
// why does this need to be a const reference?
std::istream &fin;
};
MyClass::MyClass(std::string &filename,const char quote, const char sep)
: fin(std::ifstream(filename)), owns_stream(true), sep(sep), quote(quote)
{
}
This works if I make the private fin member const. Can someone explain why?
Upvotes: 2
Views: 166
Reputation: 385385
Because you're initialising a reference from a temporary. Only const
references can do that … though it actually doesn't "work", because you have a dangling reference. This particular usage of reference-binding will not extend the temporary's life.
[C++14: 12.2/5]:
[..] The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:
- A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.
- [..]
The conventional way to do this is to accept a stream into the constructor in the first place:
MyClass(std::istream& strm, const char quote, const char sep)
: fin(strm), owns_stream(true), sep(sep), quote(quote)
{}
Then:
std::ifstream ifs("/tmp/something");
MyClass obj(ifs);
This is far more flexible for your users.
Otherwise, if you wish to mandate the use of std::ifstream
specifically, just store an actual std::ifstream
and drop the entire temporary/reference business:
class MyClass {
public:
MyClass(const std::string& filename)
: fin(filename)
{}
private:
std::ifstream fin;
};
Upvotes: 3