2015-08-26 2 views
2

Ошибка:Ошибка инициализации не-const-типа в инициализаторе конструктора?

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>}’ 

код:

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) 
{ 
} 

Это работает, если я делаю частный плавник сопзЬ член. Может кто-нибудь объяснить, почему?

ответ

3

Потому что вы инициализируете ссылку из временного. Только const ссылки могут сделать это & ​​hellip; хотя на самом деле не «работа», потому что у вас есть болтающаяся ссылка. Это конкретное использование ссылочного привязки не продлит временную жизнь.

[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.
  • [..]

Традиционный способ сделать это, чтобы принять поток в конструкторе, в первую очередь:

MyClass(std::istream& strm, const char quote, const char sep) 
    : fin(strm), owns_stream(true), sep(sep), quote(quote) 
{} 

Тогда:

std::ifstream ifs("/tmp/something"); 
MyClass obj(ifs); 

Это является гораздо более гибким для пользователей ,

В противном случае, если вы хотите, чтобы санкционировать использование std::ifstream специально, просто хранить фактический std::ifstream и падение всего временных/ссылочный бизнес:

class MyClass { 
public: 
    MyClass(const std::string& filename) 
     : fin(filename) 
    {} 

private: 
    std::ifstream fin; 
}; 
+0

хорошо, имеет смысл. У меня есть другой конструктор, который берет поток, я в основном хотел, чтобы второй конструктор был удобен в том случае, когда пользователь действительно не хотел управлять временем жизни самого потока. – Fred

+0

@Fred: О, хорошо. Это сложно. –

+0

Извините, я думал, что уже отмечен как ответ. Единственный способ, с помощью которого я могу разумно сделать это, - использовать внутренний указатель istream и распределить его по куче, если они передают имя файла или принимают адрес, если они передаются в поток (и do/do not delete на основе есть ли у меня собственность или нет). Есть ли другой подход, который мне не хватает? – Fred

Смежные вопросы