Here is my problem, I need to create X number of files and write to them depending on different factos, my solution was to create a vector of ofstream pointers like this
#include <boost/algorithm/string.hpp>
#include <vector>
#include<string>
#include <iostream>
#include <fstream>
vector<ofstream*> files;
files.resize(SplitVec.size()-4);
for(i=0;i<SplitVec.size()-4;i++)
{
line="/Users/jorge/Desktop/testing/strain_"+lexical_cast<string>(i);
cout<<"ine"<<endl;
files[i]=new ofstream(line.c_str());
}
Until this part it creates the files great, and later in the program I write to them, which is also great, my problem is when I want to close the objects, if I use:
for(i=0;i<SplitVec.size()-4;i++)
{
*files[i].close();
}
I get the following error:
In file included from main.cpp:14:./methyl.h:298: error: request for member 'close' in 'files. std::vector<_Tp, _Alloc>::operator[] [with _Tp = std::ofstream*, _Alloc = std::allocator<std::ofstream*>](1ul)', which is of non-class type 'std::ofstream*'
So, I have a question, first, why cant I call close, its a pointer to an ofstream, so with *files[i], I would have imagined I could close it, second, if I don't close it, the program works ok, but im almost sure that this is a bad practice and don't want to be a lazy or crappy programer, Ive looked as much as I could, but Ive failed finding an answer. Thank you!!!
You can store pointers in a vector just like you would anything else. Declare a vector of pointers like this: vector<MyClass*> vec; The important thing to remember is that a vector stores values without regard for what those values represent.
An ordinary vector encountered in C++ programming, is a vector of objects of the same type. These objects can be fundamental objects or objects instantiated from a class. This article illustrates examples of vector of pointers, to same object type.
Use [] Notation to Create Vector of Pointers in C++ It is similar to the regular array declaration, but in this case, we are interested in accessing each element's addresses. We are using the & (address of) operator to access pointers in the vector and print them out to the console.
Use
(*files[i]).close();
or directly
files[i]->close();
Your code is not exception safe (e.g. if an exception is thrown, since you have a vector of raw pointers, they are leaked - with the associated stream handles).
I'd suggest a modern C++ RAII approach.
For example, if you use a smart pointer like shared_ptr
(from Boost, or from C++11 <memory>
header), you could build a vector
of shared_ptr
's, and use make_shared
to allocate the ofstream
objects:
// RAII exception-safe approach
vector<shared_ptr<ofstream>> files;
// Add a new ofstream object to the vector:
files.push_back( make_shared<ofstream>( filename ) );
When the vector goes out of scope, it's destructed, and all the pointed stream objects are automatically released: very simple, clear, and exception-safe.
If you want to force streams cleanup before vector goes out of scope, you can just call .clear()
method on the vector.
(An alternative could be to use C++11 move-semantics-powered unique_ptr
, and define a vector<unique_ptr<ofstream>>
, but unfortunately there is no standard equivalent of make_shared
for unique_ptr
, and the code could be a bit more verbose, unless you write a custom implementation of make_unique
, like the one proposed by Herb Sutter.)
Note that the usual files[i]->close()
syntax applies also in this case of vector of smart pointers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With