Фон:
Я работаю по-своему, хотя книга Страуструпа c ++. Я нахожусь на главе 10, заканчивающей тренировки, и сталкиваюсь с проблемой. Теперь, насколько я могу судить, я не строго следую книге, основываясь на том, как я видел, что другие отвечают на вопросы. Я полагаю, что я только немного больше понял, как реализовать код.
Моя общая цель состоит в том, чтобы иметь функцию записи, а не иметь ее в main ().
Цель следующей функции — вернуть ofstream.
ofstream& c_data_file()
{
string oname = "mydata.txt";
ofstream ost {oname};
if (!ost) {
string error = "cannot open " + oname;
throw runtime_error(error);
}
return ost;
}
Этот код поставляется с предупреждением от компилятора, и я включаю его, так как это может быть связано с проблемой. Предупреждение:
Ссылка на стековую память, связанную с локальной переменной ‘ost’
возвращенный
ostream& operator<<(ostream& os, const Point& p)
{
return os << "(" << p.x <<"," <<p.y <<")";
}
ofstream& operator<<(ofstream& ost, const Point& p)
{
return ost << "(" << p.x <<"," <<p.y <<")";
}
ostream работает нормально (я использую этот поток еще где). Thestream не работает, возвращая ошибку:
Неконстантная lvalue ссылка на тип ofstream (он же
‘basic_ofstream’) не может связываться со значением несвязанного типа
‘basic_ostream>’
Ниже приводится остальная часть соответствующего кода:
int main() {
vector<Point> original_points;
ofstream& ost = c_data_file();
for (int i = 0; i<original_points.size(); i++) {
ost << original_points[i] << "\n";
}
ost.close();
}
Я искал онлайн весь день, следующий вопрос кажется закрытым:
перегруженный оператор << о проблемах конкатенации ofstream
Однако мне трудно понять ответ, и, насколько я понимаю, он не решает мою проблему.
Спасибо за чтение и любую помощь, которую вы можете оказать.
Я включаю следующие правки здесь, а также мой ответ на иксемонов с надеждой четко выразить проблему для всех.
Edit1: предупреждение было устранено в соответствии с рекомендациями TBBle. Основная проблема все еще остается, поскольку ссылка указывает, и иксемонов предлагает мне использовать ostream вместо ofstream. Это проблематично. Ostream (следуя книге) используется для отправки данных в cout, что я и делаю (код отсутствует). Я также хочу отправить те же данные в файл (в идеале, как книга предлагает через ofstream).
Правка 2: по ссылке и предложения иксемонова сработали. Ряд комментариев ниже помог мне выполнить предложения. Так что спасибо всем, кто прокомментировал.
Основываясь на ссылке, предоставленной OP,
перегруженный оператор << о проблемах конкатенации ofstream
кроме исправления возврат ссылки на временный ошибка, исправить это изменить
ofstream& operator<<(ofstream& ost, const Point& p)
{
return ost << "(" << p.x <<"," <<p.y <<")";
}
в
ostream& operator<<(ostream& ost, const Point& p)
{
return ost << "(" << p.x <<"," <<p.y <<")";
}
который компилируется просто отлично. Как следует из ответа в ссылке, причина возникновения ошибки заключается в том, что ost << "("
возвращает объект типа ostream
и дальнейшие звонки operator<<
таким образом, происходит сбой из-за несовместимости, сообщенной компилятором.
С другой стороны, это не очень хороший стиль, чтобы не возвращать код выхода из main, как в return 0
,
Вы создали местный ofstream
в вашей функции, поэтому вы не можете вернуть ссылку на нее, так как она исчезла после завершения вашей функции.
Так что вы должны вернуть ofstream
объект вместо
Вы не можете копировать потоки, так что это должен быть ход. К счастью, это будет автоматически в этом случае. (Предполагается, что C ++ 11. Если нет, вам нужно реструктурировать код).
И если вы находитесь на GCC до GCC 5, Вы не можете перемещать потоки из-за ошибки.
Итак, самое простое изменение вашей функции:
ofstream c_data_file()
{
string oname = "mydata.txt";
ofstream ost {oname};
if (!ost) {
string error = "cannot open " + oname;
throw runtime_error(error);
}
return ost;
}
и абонент становится
ofstream ost = c_data_file();
ofstream& c_data_file()
возвращает ссылку (&)
для ofstream ost;
который больше не существует (ofstream ost;
является локальным объектом и будет уничтожен, как только он выйдет из области видимости)
так что вы могли бы вместо этого изменить свою функцию на ofstream c_data_file()
и таким образом вы больше не будете возвращать временный объект.