Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vector of ofstream pointers

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!!!

like image 204
Jorge Kageyama Avatar asked Sep 20 '12 09:09

Jorge Kageyama


People also ask

Can I have a vector of pointers?

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.

What is a vector of pointers in C++?

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.

How to make a vector of pointers?

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.


2 Answers

Use

(*files[i]).close();

or directly

files[i]->close();
like image 112
Luchian Grigore Avatar answered Oct 01 '22 10:10

Luchian Grigore


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.

like image 44
Mr.C64 Avatar answered Oct 03 '22 10:10

Mr.C64