vectors - push_back() method

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Rasputin
    New Member
    • Jun 2007
    • 33

    vectors - push_back() method

    Hello,

    suppose I have a string temp that I want to push in a vector vec1, using:
    [code=cpp]
    vec1.pushback(t emp);
    [/code]

    I noticed that if I change the content of temp, it will change the content of vec1[lastItem], unless I push in another value after temp. Another variant to get vec1 immunized against changes in temp was to use
    [code=cpp]
    vec1.pushback(t emp.c_str());
    [/code]

    vec1 is declared like vector<string> vec1.

    pushback() awaits for a variable of type "const string&", so should I understand that the last element in the vector always points to another variable, and that only when a new value is pushed that the last value gets copied to a new location? What about the glitch with c_str()?
    Borland's 5 help thinness kills me...

    Your thoughts on this would be appreciated,

    Ras.
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    This code using Visual Studio.NET 2005 does not reproduce your problem.
    [code=cpp]
    vector<string> v;
    string temp("Hello");
    v.push_back(tem p);
    vector<string>: :iterator itr = v.begin();
    while (itr != v.end())
    {
    cout << *itr << endl;
    ++itr;
    }
    temp = "world!";
    v.push_back(tem p); //vector not changed if this commented out
    itr = v.begin();
    while (itr != v.end())
    {
    cout << *itr << endl;
    ++itr;
    }
    [/code]

    Are you sure don't have a vector<string&> ?

    C++ requires a vector be implemented as an array forcing the container to make a copy of the object placed in the container so it would be a major bug in the template if that were not true.

    Comment

    • Rasputin
      New Member
      • Jun 2007
      • 33

      #3
      Thanks for taking the time to test and answer.
      Are you sure don't have a vector<string&> ?
      Sure. I didn't even know this type of declaration was permitted. What's the applications?


      C++ requires a vector be implemented as an array forcing the container to make a copy of the object placed in the container so it would be a major bug in the template if that were not true.
      I tested your code on my compiler, and it did not produce the unexpected behaviour. It seems it's because of the nature of the modification you applied to temp.

      In my code I had something like:
      [code=cpp]
      vector<string> v;
      string temp("Say \"Hello\"");
      v.push_back(tem p); // If I replace temp by temp.c_str(), the problem does not occur
      vector<string>: :iterator itr = v.begin();
      while (itr != v.end())
      {
      std::cout << *itr << std::endl;
      ++itr;
      }
      std::strtok((ch ar*)temp.c_str( ),"\""); // Here I modify the contents of temp, ONLY. I use the char* cast and c_str() to fit the function requirements.
      itr = v.begin();
      while (itr != v.end())
      {
      std::cout << *itr << srd::endl; // KA-BOUM: Instead of 'Say "hello"', only 'Say' is displayed.
      ++itr;
      }
      [/code]

      And THIS produces the unexpected behaviour. Notice that strtok() should affect only temp.

      Would you have the kindness to test this on your compiler? Or if you noticed anything in this code to point it out to me?

      Thanks,

      Ras.

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        Originally posted by Rasputin
        Thanks for taking the time to test and answer.
        Quote:
        Originally Posted by
        Are you sure don't have a vector<string&> ?


        Sure. I didn't even know this type of declaration was permitted. What's the applications?
        You are correct here. I guess I got carried away. Usually, I compile my code examples. Obviously, this time I did not. Good catch.

        Originally posted by Rasputin
        std::strtok((ch ar*)temp.c_str( ),"\""); // Here I modify the contents of temp, ONLY. I use the char* cast and c_str() to fit the function requirements.
        This won't work. The string::c_str() method produces the contents of the string objuect as a non-modifyable C-string. Your cast cause the compiler to make a copy that is non-const. You are changing that copy.

        There is no reason to believe the string object is a C-string. Almost certainly it is not.

        Lastly, I ran your code with Visual Studio.NET and I do not see the unexpected behavior. I see:

        [code=cpp]
        Say "Hello"
        Say "Hello"
        [/code]

        Comment

        • Rasputin
          New Member
          • Jun 2007
          • 33

          #5
          Thanks for your time.

          Originally posted by weaknessforcats
          Good catch.
          This is the learner's job!


          This won't work. The string::c_str() method produces the contents of the string objuect as a non-modifyable C-string. Your cast cause the compiler to make a copy that is non-const. You are changing that copy.
          Well, in the help of my compiler I see that the declaration of strtok() is
          [code=cpp]
          char *strtok(char *s1, const char *s2)
          [/code]

          Furthermore, an example is given;
          [code=cpp]
          int main(void)
          {
          char input[16] = "abc,d";
          char *p;

          /* strtok places a NULL terminator
          in front of the token, if found */
          p = strtok(input, ",");
          if (p) printf("%s\n", p);

          /* A second call to strtok using a NULL
          as the first parameter returns a pointer
          to the character following the token */
          p = strtok(NULL, ",");
          if (p) printf("%s\n", p);
          return 0;
          }
          [/code]

          So this effectively changes the contents of s1. As for c_str(), I need it because I actually don't use std::cout for output, but the method ShowMessage(con st AnsiString msg). In Borland this function pops-up a simple dialog box with the contents of msg, which must be of type Ansistring. c_str() allows me to go from string to AnsiString. I do agree temp is not changed.

          For the outputs, I certify that using Borland 5.0 we get:
          [code=cpp]
          Say "Hello"
          Say
          [/code]
          What strikes me is that the value of temp is already pushed in the stak. Normally whatever would happen to temp should not reflect out there.

          Finally, I did not understand this:
          There is no reason to believe the string object is a C-string. Almost certainly it is not.


          Ras.

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            Originally posted by Rasputin
            Finally, I did not understand this:
            Quote:
            Originally Posted by
            There is no reason to believe the string object is a C-string. Almost certainly it is not.
            A C-string is a char array with the last element a null terminator.

            It is an assumption that the string uses this format. For example, using the templates with Visual Studio.NET. sizeof string is 32. That's a lot bigger than a struct with a char* in it. Also, there is no reason for a null termnator as the string length could be managed by a size member.

            I knoe of one STL implementation that uses a 28 byte char array and a char*. The reasoning was that most strings are 28 bytes or less. More than that and the array is not used and the char* takes over to mahange the data on the heap.

            All that's known for sure is that c_str() converts the string object to a non-modifyable C-string.

            Maybe the Borland templates use a C-string. Maybe the Borland templates are not C++ compliant so that c_str() let you chnage the string object.

            There are at least 8 STL implementation that I know of and most of the containers are implemented differently.

            The fact that you get this behavior with the Borland templates tells me that they may be older templates and that there may be newer templatws with bug fixes.

            For sure, though, in C++, you should not be using the C string library (strtok, strlen, strcmp, etc...).

            Comment

            • Rasputin
              New Member
              • Jun 2007
              • 33

              #7
              Thanks. And to finalize this dicussion, what are the options that replace:
              Originally posted by weaknessforcats
              the C string library (strtok, strlen, strcmp, etc...).

              Ras.

              Comment

              • weaknessforcats
                Recognized Expert Expert
                • Mar 2007
                • 9214

                #8
                Originally posted by Rasputin
                Thanks. And to finalize this dicussion, what are the options that replace:
                Quote:
                Originally Posted by weaknessforcats
                the C string library (strtok, strlen, strcmp, etc...).
                strtok is replaced by the various find algorithms of the STL.
                strlen is string::size()
                strcmp is string::compare () (Note the string::operato r== just calls string::compare

                Just check out the member functions for basic_string<>. string is just basic_string<ch ar>.

                Comment

                Working...