В настоящее время для записи в двоичный файл я бы написал:
file.write((char*)&toWrite, sizeof(toWrite type));
А для чтения из двоичного файла я бы написал:
file.read((char*)&readInto, sizeof(readInto type));
Но из-за этого метода чтения/записи установка значений по умолчанию в двоичный файл (для непоследовательного чтения/записи из/в файл) потребует использования буферной переменной со значениями по умолчанию:
myType defaultValues; //defaultValues is initialized with
//myType's default constructor values
file.write((char*)&defaultValues, sizeof(myType));
Я думал, что через анонимный объект это можно будет сделать в следующей, более короткой форме:
file.write((char*)&myType(), sizeof(myType)); //myType() is
//an object which is initialized by myType's default constructor values
Но поскольку анонимные объекты не являются lvalue, это невозможно.
Следовательно, возникает вопрос: есть ли способ сократить - за счет исключения необходимости определять переменную исключительно для предварительной настройки двоичного файла - предварительную настройку двоичного файла, как я сделал с анонимным объектом - просто таким образом, чтобы на самом деле будет работать?
Цель состоит в том, чтобы добавить sizeof(myType)
байт в двоичный файл, и эти байты должны быть байтами, образующими myType defaultValues
@CSStudent Я думаю, что другой комментарий имеет в виду то, что вы никогда не упоминали (в тексте), что у myType
есть конструктор по умолчанию, который инициализирует объект (ненулевыми) значениями по умолчанию. Если мое предположение верно, идея состоит в том, что вы можете захотеть изменить эти значения с помощью определения конструктора и отразить это изменение в файле. Если да, то об этом было бы неплохо упомянуть, поскольку это придает вашему коду некоторую мотивацию.
Должно быть приемлемо явно привести временное значение к ссылке, что гарантирует, что ее время жизни будет продлено до конца полного выражения. Затем вы можете получить адрес этого значения по этой ссылке:
file.write(reinterpret_cast<char const*>(&static_cast<int const&>(int())), sizeof(int));
Замените int
на свой myType
.
Но оно имеет на 100% тот же смысл, что и решение с именованной переменной во всех отношениях. В этом нет никакой пользы. Это просто делает код менее читабельным.
@user17732522 user17732522 о да, я полностью согласен. Однако я считаю, что это именно то, о чем спрашивал б/у. Они спросили, можно ли опустить отдельное объявление переменной. Вопрос о том, хороший ли это код, подлежит обсуждению. Я бы не стал кодировать это таким образом, но, тем не менее, я считаю, что полезно знать, что этого можно достичь представленным способом.
В настоящее время для записи в двоичный файл я бы написал:
file.write((char*)&toWrite, sizeof(toWrite type));
Позвольте мне прервать вопрос на этом этапе и отметить, что это немного излишне. Второй параметр полностью определяется первым, так зачем же его выписывать? Давайте создадим для этого шаблон-оболочку, чтобы сократить ваш код. (Все зависит от того, в какое пространство имен это должно войти, или, может быть, вы хотите дать ему менее распространенное имя.)
#include <iostream>
#include <type_traits>
template <class T>
requires std::is_trivially_copyable_v<T>
void write(std::ostream& out, const T& data) {
out.write(reinterpret_cast<const char*>(&data), sizeof(T));
}
Теперь писать проще
write(file, toWrite);
Примечание. Предложение requires
гарантирует, что этот шаблон будет использоваться только тогда, когда это безопасно. Например, это небезопасный способ написать std::string
. Наличие проверки компилятора является преимуществом этого шаблона. Другие предостережения в отношении этого подхода по-прежнему актуальны; его переносимость между системами не гарантируется.
Хорошо, давайте вернемся к вашему вопросу.
Но поскольку анонимные объекты не являются lvalue, это невозможно.
Хм... странно, но это уже не проблема... Я сорвал ваш вопрос?
Предложение requires
должно быть requires std::is_trivially_copyable_v<T>
. Для любых других типов он сразу будет иметь неопределенное поведение. И даже для тривиально копируемых типов результат, записанный в файл, не будет никоим образом переносимым, и его обратное чтение гарантированно будет работать только в той же системе, в которой он был записан.
@user17732522 user17732522 Спасибо. У меня больше нет оправдания «ленивости» :) поэтому я обновил ответ.
Спасибо, но зачем нужен requires std::is_trivially_copyable_v<T>
?
@CSStudent "почему требуется requires std::is_trivially_copyable_v<T>
?" -- Это достойно того, чтобы стать отдельным вопросом, а не затеряться в комментариях. См. Как узнать, можно ли записать переменную непосредственно в двоичный файл? немного справочной информации.
@JaMiT -- Спасибо!
Какова именно здесь цель? Вы хотите добавить
sizeof(myType)
байт в свой двоичный файл? Требуются ли эти байты для формирования какого-либо допустимого экземпляраmyType
, или, может быть, вы можете просто ввестиsizeof(myType)
нули?