You are here:

C++/Regarding vector of vectors

Advertisement


Question
Hi,

Please look at the following code:

dependencies(int i)
{
  string str;
  vector<string> fd;
  cout<<"enter the attributes of fd"<<i<<endl;
  cin>>str;
  fd.push_back(str);
}

int _tmain(int argc, _TCHAR* argv[])
{
  int num;
  cout<<"Enter the number of functionaldependencies"<<endl;
  cin>>num;
  for(int i=0; i<num; i++)
  {
      dependencies(i);
  }
}


In the above code I am calling the function "dependencies" depending on the given input for number of functional dependencies. In the "dependencies" function, whatever i am inputting is pushed into the vector. But everytime I call the function, the input that I give gets into the same vector.

But what i want to do is, everytime I call the function dependencies, it should create a new vector and push that iteration inputs into new vector instead of pushing into the same old vector.

Is it possible to do that way??

Please help!!

Thanks!!

Answer
I suggest you start by revising the behaviour of local automatic objects (variables) in C++.

What you describe you want is in fact happening. It is not however doing it in a way that you probably want.

Every time you make a function call _all_ local automatic objects (those created on the stack frame of the function call) in that function are created. When the function is left - whether normally via a return statement (or end of the function if the return type is void) or via a C++ exception the objects are destroyed and their destructors are called.

Thus the life time of such objects is at most the duration of the function call.

Hence every time you call the dependencies function a new vector is created, has a single string appended to it and is destroyed (along with the string object str and the copy pushed back to the vector - that is C++ standard library containers delete all their contained items when they are destroyed and make copies of the elements they are asked to hold, rather than holding references to the original item).

Further I note that you do not explicitly state the return type of the dependencies function, you declare it like so:

   dependencies(int i)

This is illegal C++ - in C you are allowed to do this and an int return type is assumed - so even if this were the case the function is still mal-formed as it returns no value. For example MSVC++ 8.0 (a.k.a. 2005) gives the following error when I pasted you function in to a convenient source file:

   main.cpp(152) : error C4430: missing type specifier - int assumed.
   Note: C++ does not support default-int
In C++ you _must_ explicitly state the return type of functions, and in both C and C++ if a function returns no value (i.e. it is a procedure) then it should explicitly state a void return type:

   void dependencies(int i)

I also note from your use of the non-standard _tmain and _TCHAR that you are probably using a Microsoft compiler or one that supports at least some MS C/C++ specific features. Note that some MS compilers - the older ones in particular - are not all that standard in their understanding of C++.

So maybe fd was supposed to be a local static object, such that its life time is from the first call of dependencies to the end of the program? Or maybe you are trying to return a vector to the caller (this does not seem to be the case in the code you show)?

Assuming the static local object case, as this seems nearer to you existing code, you just left off the static qualifier to the declaration of fd, you could have many vectors by having a collection of vectors, for example a vector of vectors:


   static std::vector< std::vector<std::string> > vfd;

   vfd.push_back( std::vector<string>() );

   // ...

   vfd.back().push_back( str );

Here I define a vector that contains as elements vectors of std::string objects. This is a local static object so will be created on the first call (and only on the first call) to dependencies and exists until the program terminates - i.e. it exists between function calls. I call this vfd - for vector of fd.

Each time dependencies is called a new vector of strings is appended to vfd. I then modify the way in which the string entered is appended to a vector. I select the last vector of string in vfd (i.e. the one just added) using vfd.back() and call push_back on this vector of strings to append the string to it.

I suspect that what you would really require is that the value i is associated with a particular vector of strings. In this case we can modify our example like so:

   string str;
   static std::vector< std::vector<std::string> > vfd;
   if ( vfd.size() <= i )
   {
       vfd.resize(i+1);
   }

   // ...

   vfd[i].push_back( str );

Here I again create vfd as before. However this time we check to see if we have enough vectors based on the value of i. If the size of vfd (the number of vector of strings it contains) is less than or equal to the value of i then we need to resize the vector to accommodate the extra size. The check for this is if i is zero then we need at least 1 item in vfd - thus we need to resize vfd to 1 (or greater) - which is 0 + 1 or i + 1. Note that resize may copy the exiting data in the vector elsewhere (as more memory may be required) and the new item(s) are created using their default constructor, which is all OK for our requirements. We could prevent too many initial resizes by pre-allocating enough space for a few vector of string elements when vfd is created:

   static std::vector< std::vector<std::string> > vfd(5);

Note in the above variant that I have passed a value of 5 to initialise vfd with. This effectively resizes vfd to 5 elements before we start. However whether this is really much of a performance saver is debatable as std::vector types perform such tricks themselves internally to ensure they do not have to re-allocate memory and copy the contents more than necessary.

I cannot see much point to the pieces of code you show - so must assume you are only showing fragments of the whole code to demonstrate your point. I would still ask: what are you really trying to achieve? I ask as you may be better solutions. For example - use a class that contains a string, or std::vector<std::string> as appropriate then have main (or _tmain) hold a vector of objects of this class type. The class could have instance member functions to operate on individual strings or string vectors.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.