Reputation: 121
I'm having difficulty returning an array of string vectors. I have a function:
std::vector<std::string>* generatecVec(std::vector<std::string> strVec){
std::vector<std::string> cVec[3];
cVec[0].push_back("Test11");
cVec[0].push_back("Test12");
cVec[0].push_back("Test13");
cVec[1].push_back("Test21");
cVec[1].push_back("Test22");
cVec[1].push_back("Test23");
cVec[2].push_back("Test31");
cVec[2].push_back("Test32");
cVec[2].push_back("Test33");
return cVec;
}
and later I use the function like
std::vector<std::string> *cVec = generatecVec(strVec);
for(std::vector<string>::iterator it = cVec[0].begin(); it != cVec[0].end(); ++it) {
std::cout << *it;
}
but I keep getting segmentation fault. I realize I must be using pointers improperly, but how might I fix this? I use the array of vectors because it is very easy to refer to it by index (I only need three, non dynamic). Thanks!
Upvotes: 1
Views: 12327
Reputation: 2519
As the others already explained, you are returning a local reference, that is garbage outside the function scope. As a rule of thumb I try to avoid raw pointers as much as possible, since eventually I forget to delete a pointer after usage, or to initialize a pointer to start with.
When you return a std::array or std::vector you invoke the copy constructor and receive a fresh copy of the vector,array,etc... I personally tend to use boost shared_ptr for these situations, as they overcome most disadvantages that come with the classic C pointers
Upvotes: 1
Reputation: 44238
It is strange that you use vector of string when you need collection of strings, but pointer when you need collection of vectors. Using typedef should help with abstraction of details and see possible solution:
typedef std::vector<std::string> strings;
typedef std::vector<strings> strings_seq;
strings_seq generateVec()
{
strings_seq cVec( 3 );
cVec[0].push_back("Test11");
cVec[0].push_back("Test12");
cVec[0].push_back("Test13");
cVec[1].push_back("Test21");
cVec[1].push_back("Test22");
cVec[1].push_back("Test23");
cVec[2].push_back("Test31");
cVec[2].push_back("Test32");
cVec[2].push_back("Test33");
return cVec;
}
Upvotes: 0
Reputation: 75130
You're returning a pointer to an automatic array, which is destroyed as it goes out of scope and your pointer points to a destroyed array full of destroyed vectors.
Use std::array
and return it by value:
// This means: std::array of 3 std::vector<string>
// Type--VVVVVVVVVVVVVVVVVVVVVVVV V-- Array size
std::array<std::vector<std::string>, 3> generatecVec(std::vector<std::string> strVec){
return { {
{ "Test11", "Test12", "Test13" },
{ "Test21", "Test22", "Test23" },
{ "Test31", "Test32", "Test33" }
} };
}
auto cVec = generatecVec(strVec);
for(auto it = cVec[0].begin(); it != cVec[0].end(); ++it) {
std::cout << *it;
}
Upvotes: 0
Reputation: 227390
You are returning a pointer to something that only lives in the scope of the function. Once the function is done, cVec
vanishes and the caller is left with a dangling pointer. I suggest returning an object that can actually be copied, such as an std::array<std::vector<std::string> 3>
.
#include <array> // for std::array
std::array<std::vector<std::string>,3> generatecVec(/*std::vector<std::string> strVec*/){
std::array<std::vector<std::string>,3> cVec;
cVec[0].push_back("Test11");
cVec[0].push_back("Test12");
cVec[0].push_back("Test13");
cVec[1].push_back("Test21");
cVec[1].push_back("Test22");
cVec[1].push_back("Test23");
cVec[2].push_back("Test31");
cVec[2].push_back("Test32");
cVec[2].push_back("Test33");
return cVec;
}
I have commented out strvec
here because it seems to play no role in the function.
You can then use it like this (C++11 range based for loop syntax):
auto cVec = generatecVec(); // no strVec because it doesn't play any role
for(auto it = cVec[0].cbegin(); it != cVec[0].cend(); ++it) {
std::cout << *it;
}
Note that the push_backs
may not be necessary if your compiler supports C++11 initializer list initialization.
If your compiler doesn't support std::array
, try std::tr1::array
from , or boost::array
.
Upvotes: 5