Запись/чтение из двоичного файла без объявления буферной переменной, но через анонимный объект

В настоящее время для записи в двоичный файл я бы написал:

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, или, может быть, вы можете просто ввести sizeof(myType) нули?

Fureeish 30.06.2024 19:24

Цель состоит в том, чтобы добавить sizeof(myType) байт в двоичный файл, и эти байты должны быть байтами, образующими myType defaultValues

CS Student 30.06.2024 19:27

@CSStudent Я думаю, что другой комментарий имеет в виду то, что вы никогда не упоминали (в тексте), что у myType есть конструктор по умолчанию, который инициализирует объект (ненулевыми) значениями по умолчанию. Если мое предположение верно, идея состоит в том, что вы можете захотеть изменить эти значения с помощью определения конструктора и отразить это изменение в файле. Если да, то об этом было бы неплохо упомянуть, поскольку это придает вашему коду некоторую мотивацию.

JaMiT 30.06.2024 20:15
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
110
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Должно быть приемлемо явно привести временное значение к ссылке, что гарантирует, что ее время жизни будет продлено до конца полного выражения. Затем вы можете получить адрес этого значения по этой ссылке:

file.write(reinterpret_cast<char const*>(&static_cast<int const&>(int())), sizeof(int));

Замените int на свой myType.

Но оно имеет на 100% тот же смысл, что и решение с именованной переменной во всех отношениях. В этом нет никакой пользы. Это просто делает код менее читабельным.

user17732522 30.06.2024 21:30

@user17732522 user17732522 о да, я полностью согласен. Однако я считаю, что это именно то, о чем спрашивал б/у. Они спросили, можно ли опустить отдельное объявление переменной. Вопрос о том, хороший ли это код, подлежит обсуждению. Я бы не стал кодировать это таким образом, но, тем не менее, я считаю, что полезно знать, что этого можно достичь представленным способом.

Fureeish 01.07.2024 00:12
Ответ принят как подходящий

В настоящее время для записи в двоичный файл я бы написал:

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 30.06.2024 21:33

@user17732522 user17732522 Спасибо. У меня больше нет оправдания «ленивости» :) поэтому я обновил ответ.

JaMiT 30.06.2024 23:16

Спасибо, но зачем нужен requires std::is_trivially_copyable_v<T>?

CS Student 02.07.2024 18:25

@CSStudent "почему требуется requires std::is_trivially_copyable_v<T>?" -- Это достойно того, чтобы стать отдельным вопросом, а не затеряться в комментариях. См. Как узнать, можно ли записать переменную непосредственно в двоичный файл? немного справочной информации.

JaMiT 03.07.2024 06:36

@JaMiT -- Спасибо!

CS Student 07.07.2024 14:12

Другие вопросы по теме