简体   繁体   中英

basic_ofstream<int> vs. basic_ofstream<char>

I trying to understand std::basic_ofstream . I started with this:

#include <fstream>

int main() {
    std::ofstream test_stream("data.txt");
    int my_int = 12;
    double my_double = 26.8;
    test_stream << my_int << " " << my_double;
}

When you open data.txt in Notepad, you see

12 26.8

This told me that << formatted the output and stored the output as char s ( cppreference ). Indeed, the size of data.txt was 7 bytes.

I wanted to output my data as raw bits to prevent conversion to strings. I found I could do that with write :

test_stream.write((char*) & my_int, 4);
test_stream.write((char*) & my_double, 4);

This functionally does what I want/expected. data.txt will appear as 12 bytes that are the little endian, binary representation of 12 and 26.8. However, I was hoping for some nicer notation. I tried the put member function, but that only outputs 1 byte of the int .

I then considered the possibility of changing basic_ofstream 's character type to int . My hope was that I could do something like this

int main() {
    std::basic_ofstream<int> test_stream("data.txt");
    int my_int = 123412431;
    test_stream.put(my_int);
}

or this

int main() {
    std::basic_ofstream<int> test_stream("data.txt");
    int my_int = 123412431;
    test_stream << my_int;
}

The first gives only 1 byte output Ï . The second gives an error. I assumed that the point of std::basic_ofstream<int> would be to overload put to transfer int s.

Question

So what is the difference between std::basic_ofstream<int> and std::basic_ofstream<char> ? Is there a way to make std::basic_ofstream<int> do what I want? (for clarity: what I want is the functionality of the write example with put or << .)

int is not a character type. You cannot use it as template argument to std::basic_ostream .

(Technically it may be supported as implementation-defined character type, but I don't think any implementation actually does that.)

Only char (corresponding to std::ostream ) and wchar_t (corresponding to std::wostream ) are generally supported.


Your approach of outputting the object representation with std::ofstream is correct and how it should be done, except that you should use reinterpret_cast<const char*> instead of (char*) and that you should use sizeof(/*variable name*/) instead of a magic number. Both of these help avoid mistakes.

You can wrap that in a function to have nicer notation which doesn't require repeating the variable name twice:

template<typename T>
std::ostream& print_object_representation(std::ostream& o, const T& t) {
    // Use `std::addressof(t)` instead of `&t` to
    // correctly handle classes with overloaded `operator&`
    o.write(reinterpret_cast<const char*>(&t), sizeof(t));
    return o;
}

//...

print_object_representation(test_stream, my_double);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM