Aurélie JEAN
Aurélie JEAN

Reputation: 195

Why can I have a std::vector<std::ofstream*> but not a std::vector<std::ofstream>?

I have the following test code in which I have a parameter fS which is a container of ofstreams:

    #include <fstream>
    #include <vector>
    #include <cstdlib>
    #include <cstdio>

    int main()
    {
        // my container of ofstream(s)
        std::vector<std::ofstream> fS;

        // instantiate an ofstream
        std::ofstream of("myfile.txt");

        // push back to my container
        fS.push_back(of);

        return 0;
    }

This does not compile at all. Whereas when I change the container of ofstream into a container of pointers to ofstreams, the code compiles:

    #include <fstream>
    #include <vector>
    #include <cstdlib>
    #include <cstdio>

    int main()
    {
        // my container of ofstream(s)
        std::vector<std::ofstream*> fS;

        // instantiate an ofstream
        std::ofstream * of = new std::ofstream("myfile.txt");

        // push back to my container
        fS.push_back(of);

        return 0;
    }

Why is this?

Upvotes: 2

Views: 2160

Answers (1)

templatetypedef
templatetypedef

Reputation: 373042

When you call push_back(of) on a vector, it tries to add a copy of the object of to the vector. (C++ loves making copies of things). In this case, you're trying to copy an ofstream, which isn't permitted. Intuitively, it's not clear what it would mean to have a copy of an ofstream, so the spec prohibits it.

On the other hand, suppose you have a vector of ofstream*s. Now, if you try to push_back a pointer to an ofstream, then C++ interprets this to mean that you should put a copy of the pointer into the vector, and that's okay because pointers can easily be copied around.

There's a third option, though, if you have a recent compiler. C++ recently introduced the idea of move semantics, that instead of trying to copy the file stream into the vector, you can move the file stream into the vector. You could therefore write something like this:

int main()
{
    // my container of ofstream(s)
    std::vector<std::ofstream> fS;

    // instantiate an ofstream
    std::ofstream of("myfile.txt");

    // push back to my container
    fS.push_back(std::move(of));

    return 0;
}

After doing this, the variable of won't refer to the original file stream anymore; it'll instead just have some dummy value. However, the vector will now effectively contain the stream that used to be stored in of.

Upvotes: 3

Related Questions