CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Dec 2005
    Posts
    254

    Initializing A Vector Of Vectors Of Strings

    I thought that C++0x made it possible for vectors to be initialized with an initializer list, such as:

    Code:
    vector<vector<string> > vv {{"hello", "goodbye", ""}};
    I tried this syntax in both VS 2010 & VS 2012 Express For Desktop, and I get the same error in both compilers:

    compiler error: non-aggregates cannot be initialized with initializer list


    To put the code above in context, I'm going to have a .txt file with hundreds of thousands of string arrays, in initializer list format, such as:

    {"string","string","string","","",""},{"string","string","string","","",""},{"string","string","string","","",""}...and so on

    The first 3 strings in each array will be non-zero in length, and the last 3 strings in each array will be empty, as shown above.

    I want to be able to cut and paste the arrays right into the declaration, either with:

    string arrayOfArrays[0][6] = {{"string","string","string","","",""},{"string","string","string","","",""},{"string","string","string","","",""}...and so on };

    or

    vector<vector<string> > vecOfVectors = {{"string","string","string","","",""},{"string","string","string","","",""},{"string","string","string","","",""}...and so on };

    I know I can do the first, but apparently the second declaration method with vectors won't work. I would like to work with vectors, but I'm not sure about the initialization. The .txt file will be what it is, so the initialization will have to be able to work with its 'array-like initializer' format.

  2. #2
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Initializing A Vector Of Vectors Of Strings

    Quote Originally Posted by spiritualfields View Post
    I tried this syntax in both VS 2010 & VS 2012 Express For Desktop, and I get the same error in both compilers
    initializer lists are not supported by vs2010; vs2012 supports them starting from the november 2012 CTP release, hence your vs2012 copy probably doesn't support them either.

    Anyway, yes, your code is correct as far as c++11 is concerned.

    Quote Originally Posted by spiritualfields View Post
    To put the code above in context, I'm going to have a .txt file with hundreds of thousands of string arrays, in initializer list format
    why do you need such a thing ? it looks like you're somehow trying to "optimize" something by this machinery or enforce some form of static initialization, but then why using string's and vector's ? if you just want to store and access so many strings efficiently then other solutions could be more appropriate ...
    Last edited by superbonzo; December 6th, 2012 at 04:07 AM.

  3. #3
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Initializing A Vector Of Vectors Of Strings

    Would std::array be a happy compromise?
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  4. #4
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Initializing A Vector Of Vectors Of Strings

    if you have "large" initialiser lists (and hundreds of thousands would qualify) then know that a vector initializer list will "behind the scenes" generate code to fill a vector. The vector itself will still be allocted via the memory store and each member will be constructed/copied.
    the vector after initalisation will ehave like a normal vector and will allow removal, insertion, adding. Even if you make it const, it won't change the fact that it is a dynamic allocated structure.

    Additionally, since you use string: The string themselves will be constructed, and the literal character bytes that form the string's contents from your initializer will be COPIED into the string's internal storage. Once this is done, you can iterate the strings as normal, and you can modify the strings.
    Your running process will thus have the literal string value stored somewhere in a readonly section, and it will have been copied into either the strings internal buffer (since it's in a vector, it'll be on the memory store) or if that internal buffer is too small will be in an allocated buffer via the memory store.



    This may be exactly what you want, or it may not be. If what you are after is readonly static data in a readonly section of your exe, then std::array is a better fit, but you'll also need to use const char* instead of string to prevent "copying" the string contents. (or an implementation of a static const string container based on a const char*).


    --
    Additionally, that many literal strings may cause some compiler/linker issues because you'll have a huge symbol table. Compilation/linking may be *very* slow (I have logged several issues on MS Connect for a similar problem where I'm having many many megabytes worth of static const data in arrays). To work around compiler/linker issues, I even had to develop my own string pooling mechanism. I had to make this work for VS2010 which MS isn't updating anymore, some of the issues I had should be solved in VS2012.

  5. #5
    Join Date
    Dec 2005
    Posts
    254

    Re: Initializing A Vector Of Vectors Of Strings

    Quote Originally Posted by JohnW@Wessex View Post
    Would std::array be a happy compromise?
    I don't know. My knowledge of STL is weak. What I need is a container of string arrays, like this:

    Code:
    SOME_CONTAINER_WITH_ELEMENTS_ACCESSIBLE_BY_INDEX
    {
       {"hello", "string", "string", "", "", ""} //[0][0] = "hello"
       {"string", "string", "good", "", "", ""}// [1][2] = "good"
       and so on
    }
    An array of arrays, or a vector of vectors, or some type of container of containers. I did this sort of thing once before with MFC's string arrays, but I had to do a tremendous amount of coding to get the container's elements to do what I wanted. This time I was hoping to use the stl and save some brain cells by using the stl's built-in functions.

  6. #6
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Initializing A Vector Of Vectors Of Strings

    Quote Originally Posted by spiritualfields View Post
    SOME_CONTAINER_WITH_ELEMENTS_ACCESSIBLE_BY_INDEX
    well then, why not something like:

    Code:
    const char* arrayOfArrays[][6] = {{"string","string","string","","",""},{"string","string","string","","",""},{"string","string","string","","",""}};
    the above is accessible by index, it's STL interoperable ( moreover, it could be made regular (aka copyable) by making it a member of some aggregate struct ) and no copy/move of strings is required. That said, I'm still curious about why are you using a global variable to store such a big list of strings ...

  7. #7
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Initializing A Vector Of Vectors Of Strings

    Quote Originally Posted by superbonzo View Post
    well then, why not something like:

    Code:
    const char* arrayOfArrays[][6] = {{"string","string","string","","",""},{"string","string","string","","",""},{"string","string","string","","",""}};
    the above is accessible by index, it's STL interoperable ( moreover, it could be made regular (aka copyable) by making it a member of some aggregate struct ) and no copy/move of strings is required. That said, I'm still curious about why are you using a global variable to store such a big list of strings ...
    The above will work, but won't work (well) with some of the stl algorithms.
    and it excludes the use of iterators on the arrayOfArrays (you'll have to use normal indexing).

    You can work around the above by using std::array
    the difference between vector and array is that vector is a dynamic allocated array that can grow and shrink as needed, an array behaves exactly like a vector in (almost) all ways, except that you can't make it smaller/bigger (the number of elements is fixed)


    Why would you do the above?
    if what you are after is an array that is preinitialized at compile time (i.e. there is no code to "fill" the array at all) and resides in the readonly section then it HAS to be either global or class static (which is sort of the same from the technical p.o.v.).

    somethign like:
    std::vector<int> v = { 1 , 2 , 3 };
    will actually cause the compiler to generate the code (which needs to be executed at runtime) to get the desired resultant vector.
    with a std::array, depending on how you defined the array this may or may not also be the case. if you define the std::array as const, then it might be able to skip the code if the elements of the array are simple types that don't need a constructor.

    the distinction can be significant for large tables. Because with a vector (or types that need construction), you would have a significant amount of code and supporting data in the exe that are used to construct the container and/or the elements. As well as ending up with the (allocated) memory for the actual container and it's elements.

    In the case of my own program where I had several hundres MB worth of data, it was quite critical to make sure I wasn't copying any data into the container or it's elements, but that the container WAS the readonly data in the executable image.

  8. #8
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Initializing A Vector Of Vectors Of Strings

    Quote Originally Posted by OReubens View Post
    Why would you do the above?
    if what you are after is an array that is preinitialized at compile time (i.e. there is no code to "fill" the array at all) and resides in the readonly section then it HAS to be either global or class static (which is sort of the same from the technical p.o.v.).
    yeah, this was the first thing that came to my mind too but then I saw that the OP used vector's and string's; so I doubt this is his actual intent.

    Quote Originally Posted by OReubens View Post
    it excludes the use of iterators on the arrayOfArrays (you'll have to use normal indexing).
    what do you mean ? unless I'm missing something, you can write things like

    Code:
    const char* arrayOfArrays[][6] = {{"1","2","3","","",""},{"4","5","6","","",""},{"7","8","9","","",""}};
    
    // "iterator" based ith access
    
    std::for_each( arrayOfArrays[2], std::end(arrayOfArrays[2]), []( const char* str ){
            std::cout << str << std::endl;
        } );
    
    // nested "iterator" access
    
    std::for_each( arrayOfArrays, std::end(arrayOfArrays), []( const char* (&strings)[6] ){
            std::for_each( strings, std::end(strings), []( const char* str ){
                    std::cout << str << std::endl;
                } );
        } );
    moreover, generic functions taking containers as input should follow the range-access idiom (eg. unqualified calls to begin(container),end(container), use of iterator traits ... ) making c-arrays and std::array's essentially equivalent from a container-access pov, the only difference being that the latter is a semiregular type ( and some other minor differences, like the support of 0-sized std::array's ... ).
    Last edited by superbonzo; December 7th, 2012 at 09:49 AM. Reason: added final comment

  9. #9
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Initializing A Vector Of Vectors Of Strings

    Quote Originally Posted by superbonzo View Post
    yeah, this was the first thing that came to my mind too but then I saw that the OP used vector's and string's; so I doubt this is his actual intent.
    you''d be surprised at how many (even experienced) C++ programmers don't see the difference between a compile time initialized structure and a run time initialized structure. Or if they do understand the difference, don't quite grasp the actual implication on the running executable.

    Quote Originally Posted by superbonzo View Post
    What do you mean ? unless I'm missing something, you can write things like
    most (all?) of the STL will work with a regular C-style array for sure.
    But I've seen several template libraries that assume the .begin() and .end() are present in the containers that that wouldn't work with regular arrays.
    from a coding perspective, even when using the STL, it means you have to be aware it's not a container, but a regular array and needs to be treated differently.

    In the 2nd case example you give, it even requires you to know/repeat that the 2nd dimention is 6. If at some point you change it to somethign else, you have to go change other code as well. Yes, you can use an separate define/const for that, but that requires some forethought, again, something many novices we see at our company are lacking.
    There's a reason I ranted on the C++ excercise post maybe more than I should have, I'm quite displeased with how 'kids' are taught how to program in C++ at school. >.<


    So yes, this'll work, but there's a reason we (C++ programmers) have evolved to use containers

  10. #10
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Initializing A Vector Of Vectors Of Strings

    and I agree with you, I just felt the word "exclude" a bit too strong

    Quote Originally Posted by OReubens View Post
    In the 2nd case example you give, it even requires you to know/repeat that the 2nd dimention is 6.
    note that you can also use iterator traits to deduce the value_type automatically, so a properly written fully generic version of such a code would work ok without any specific treatment of the c-array case. That said, I fully agree with you ...

  11. #11
    Join Date
    Dec 2005
    Posts
    254

    Re: Initializing A Vector Of Vectors Of Strings

    Quote Originally Posted by OReubens View Post
    The above will work, but won't work (well) with some of the stl algorithms.
    and it excludes the use of iterators on the arrayOfArrays (you'll have to use normal indexing).

    You can work around the above by using std::array
    the difference between vector and array is that vector is a dynamic allocated array that can grow and shrink as needed, an array behaves exactly like a vector in (almost) all ways, except that you can't make it smaller/bigger (the number of elements is fixed)
    That's EXACTLY why I wanted to work with vectors. The user will not be able to delete elements (which themselves are arrays of strings), but they will be able to insert new elements, and write into the empty strings of all the pre-existing elements (each pre-existing element in the container will be of the form: {"string","string","string","","",""},).

    Pre-initialization is important. The data is in a file in this format: {"string","string","string","","",""}, {"string","string","string","","",""},and so on} that I have to get into the code somehow.

    I'm thinking that I could declare an array of string arrays (string arrOfArrays[][6]), initialize it with the data with a humongous initializer list to get it into the code, and then loop through the elements, pushing them into a vector<vector<string>>.

    I was hoping to just directly initialize the vector with an initializer list, but apparently that's not possible yet.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured