Thread: State of string.length()

  1. #1
    Registered User
    Join Date
    Dec 2005
    Posts
    32

    State of string.length()

    Hello! Quick question here, since I haven't gotten any good C++ reference books yet.

    Is the string length calculated each time string.length() is called, or is the value always kept "up-to-date" somewhere in the object?

    Thanks!
    -tretton

  2. #2
    Registered User major_small's Avatar
    Join Date
    May 2003
    Posts
    2,787
    well, AFAIK, that's really up to implementation, but you should probably figure that it's going to calcuate it whenever you call length().
    Join is in our Unofficial Cprog IRC channel
    Server: irc.phoenixradio.org
    Channel: #Tech


    Team Cprog Folding@Home: Team #43476
    Download it Here
    Detailed Stats Here
    More Detailed Stats
    52 Members so far, are YOU a member?
    Current team score: 1223226 (ranked 374 of 45152)

    The CBoard team is doing better than 99.16% of the other teams
    Top 5 Members: Xterria(518175), pianorain(118517), Bennet(64957), JaWiB(55610), alphaoide(44374)

    Last Updated on: Wed, 30 Aug, 2006 @ 2:30 PM EDT

  3. #3
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    A std::string is allowed to contains NULs, so it HAS to save the length.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  4. #4
    Registered User
    Join Date
    Aug 2005
    Posts
    1,267
    Quote Originally Posted by CornedBee
    A std::string is allowed to contains NULs, so it HAS to save the length.
    Not necessarly -- capacity() is the number of byte the string class has allocated for the data. size() and length() are both the same and is the count of the number of characters up to the first 0. In the below example, the assignment operator changes the capacity to the number of characters including 0s in the entire string, while memcpy does not change the original allocated string's capacity.
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main()
    {
    	std::string str;
    	str.resize(255);
    	memcpy((char*)str.data(), "Hello\0World\0Now\0", 16);
    	cout << "str.capacity() = " << str.capacity() << endl;
    	cout << "str.size() = " << str.size() << endl;
    	cout << "str.length() = " << str.length() << endl;
    	cout << endl;
    
    	str = "Hello\0World\0Now\0";
    	cout << "str.capacity() = " << str.capacity() << endl;
    	cout << "str.size() = " << str.size() << endl;
    	cout << "str.length() = " << str.length() << endl;
    
    	return 0;
    
    }
    output
    Code:
    str.capacity() = 255
    str.size() = 255
    str.length() = 255
    
    str.capacity() = 31
    str.size() = 5
    str.length() = 5
    Press any key to continue
    [edit]A bit more testing shows that the assignment operator stops copying characters when it encounters the first 0 byte. So you can't use the assignment operator with strings that contain embedded null bytes.

    Changing the first 0 to a space (or some other readable character) does not change the string's length(), so the value returned by length() is an internal class integer the represents the string's length only when the std::string's contents are changed by one of std::string's method, such as one of the operators. std::string does not perform strlen() each time length() is called. [/edit]
    Last edited by Ancient Dragon; 01-07-2006 at 07:20 AM.

  5. #5
    Registered User
    Join Date
    Dec 2005
    Posts
    32
    Thank you, everyone!

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Ancient Dragon
    Not necessarly -- capacity() is the number of byte the string class has allocated for the data. size() and length() are both the same and is the count of the number of characters up to the first 0.
    Corndbee is right in saying that a std::string is allowed to contain multiple NULL bytes. There is, however, an issue that, when given standard C-style strings, that std::string member functions (constructors, assignment, etc) only copy up to the first NULL byte. If you want to get multiple NULL bytes into a std::string, you have to jump through a few more hoops, and converting such a std::string back to a C-style string will mean you don't see all the contents of the std::string.

    As to whether that means that a std::string needs to store it's length, I'm not so sure, but suspect Corndbee is correct: by providing the data() method, the definition of std::string implicitly rules out implementations of std::string based on (say) a linked list of nodes, each containing a byte.
    Quote Originally Posted by Ancient Dragon
    In the below example, the assignment operator changes the capacity to the number of characters including 0s in the entire string, while memcpy does not change the original allocated string's capacity.
    I wouldn't expect it to, memcpy() only works with raw memory, and does not cooperate if the memory it works with happens to belong to a std::string (or any other class type, for that matter).
    Quote Originally Posted by Ancient Dragon
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main()
    {
    	std::string str;
    	str.resize(255);
    	memcpy((char*)str.data(), "Hello\0World\0Now\0", 16);
    	cout << "str.capacity() = " << str.capacity() << endl;
    	cout << "str.size() = " << str.size() << endl;
    	cout << "str.length() = " << str.length() << endl;
    	cout << endl;
    The snippet above would not change any of the members you are printing out. If you were to copy more than 255 bytes (or the string was of length 15 or less) the result would be undefined behaviour.
    Quote Originally Posted by Ancient Dragon
    Code:
    	str = "Hello\0World\0Now\0";
    	cout << "str.capacity() = " << str.capacity() << endl;
    	cout << "str.size() = " << str.size() << endl;
    	cout << "str.length() = " << str.length() << endl;
    
    	return 0;
    
    }
    output
    Code:
    str.capacity() = 255
    str.size() = 255
    str.length() = 255
    
    str.capacity() = 31
    str.size() = 5
    str.length() = 5
    Press any key to continue
    [edit]A bit more testing shows that the assignment operator stops copying characters when it encounters the first 0 byte. So you can't use the assignment operator with strings that contain embedded null bytes.
    That's the way it's supposed to be. But that doesn't mean a std::string cannot contain more than one null byte. It's just an artifact of how assignment to a C-style string works.
    Quote Originally Posted by Ancient Dragon
    Changing the first 0 to a space (or some other readable character) does not change the string's length(), so the value returned by length() is an internal class integer the represents the string's length only when the std::string's contents are changed by one of std::string's method, such as one of the operators. std::string does not perform strlen() each time length() is called. [/edit]
    This last observation is correct. However, try a test based on this;
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main()
    {
    	std::string str;
    
            char temp[] = "Hello\0World\0Now\0";
    	for (int i = 0; i < sizeof(temp); ++i)
               str.append(temp[i]);
    
    	cout << "str.capacity() = " << str.capacity() << endl;
    	cout << "str.size() = " << str.size() << endl;
    	cout << "str.length() = " << str.length() << endl;
    
    	return 0;
    
    }
    and you'll find the results are a bit different.

  7. #7
    Registered User
    Join Date
    Aug 2005
    Posts
    1,267
    grumpy: Where did I, or any else for that matter, say std::string could not contain more than one 0?
    If you were to copy more than 255 bytes (or the string was of length 15 or less) the result would be undefined behaviour.
    Agree -- more than 255 characters is simply C buffer overflow behavior, but I don't see where copying less than 15 characters would be a problem when the buffer will hold up to 255 characters.

    Code:
               str.append(temp[i]);
    won't compile -- no append() overrides take char.

  8. #8
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Ancient Dragon
    Code:
               str.append(temp[i]);
    won't compile -- no append() overrides take char.
    That's what I get for typing too fast rom memory rather than having the standard at hand; one of many minor anomolies in the standard.

    Try
    Code:
    str.append(1, temp[i]);
    or
    Code:
    str += temp[i];

  9. #9
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by grumpy
    That's what I get for typing too fast rom memory rather than having the standard at hand; one of many minor anomolies in the standard.
    Peculiar indeed.
    You could use push_back() instead

    Not on VC++6 with its original library, though. At least you need a STL replacement.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Finite State Machine
    By ArlexBee-871RBO in forum C++ Programming
    Replies: 8
    Last Post: 07-14-2008, 11:59 AM
  2. Grammar to FSA to C code (Newbie)
    By aybe in forum C Programming
    Replies: 4
    Last Post: 02-29-2008, 02:10 PM
  3. input/switch statement issues
    By peanut in forum C Programming
    Replies: 5
    Last Post: 10-27-2006, 02:58 PM
  4. NAQ: Everything you never wanted to know about CPP
    By evildave in forum C Programming
    Replies: 21
    Last Post: 12-12-2005, 10:56 AM
  5. Finite State Machine Project Help
    By ryanbradley in forum C++ Programming
    Replies: 4
    Last Post: 03-06-2004, 10:23 AM