Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does std:string prevent me from carelessly stomping on its data?

Tags:

c++

arrays

string

I have the following C++ code:

#include <string>
#include <iostream>


int main(int argc, char** argv)
{
    int size;
    std::string strArray[3];
    std::string str0 = "String 0";
    std::string str1 = "String 1";
    std::string str2 = "String 2";

    strArray[0] = str0;
    strArray[1] = str1;
    strArray[2] = str2;

    for (int i = 0; i < 3; i++)
    {
        std::cout << strArray[i] << std::endl;
    }

    str1.resize(200, 'a');

    for (int i = 0; i < 3; i++)
    {
        std::cout << strArray[i] << std::endl;
    }

    std::cout << str1 << std::endl;

    std::cin.get();
    return 0;
}

The idea here is that I have an array which is a contiguous block of memory, where each member is a std::string, which are mutable and therefore variable in size. I expected this code to break since I resize str1 to take up loads more space than original, and therefore "overflowing" into str2.

Instead I get this output:

String0

String1

String2

String0

String1

String2

String1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...

I have two questions about this. First of all, how is it that increasing the size of str1 and adding loads of characters to it does not flow over into str2 even though they should be in a contiguous block of memory?

Second, how come when I print the array for the second time after resizing str1 AND add the characters to it it still prints the original str1? I have a feeling that this will have something to do with the answer to my first question but I can't quite see what is going on here.

like image 640
Noodles Avatar asked Sep 17 '14 22:09

Noodles


People also ask

How does std string work?

std::string class in C++ C++ has in its definition a way to represent a sequence of characters as an object of the class. This class is called std:: string. String class stores the characters as a sequence of bytes with the functionality of allowing access to the single-byte character.

What does string mean in C++?

One of the most useful data types supplied in the C++ libraries is the string. A string is a variable that stores a sequence of letters or other characters, such as "Hello" or "May 10th is my birthday!". Just like the other data types, to create a string we first declare it, then we can store a value in it.

What is the c++ string class?

string class is part of C++ library that supports a lot much functionality over C style strings. C++ string class internally uses char array to store character but all memory management, allocation, and null termination is handled by string class itself that is why it is easy to use.

Is std :: string a pointer?

The c_str method of std::string returns a raw pointer to the memory buffer owned by the std::string . The pointer is only safe to use while the std::string is still in scope. When the std::string goes out of scope, its destructor is called and the memory is deallocated, so it is no longer safe to use the pointer.


3 Answers

The array of string objects is contiguous, but the actual string data is stored on the heap*, so the string data itself is not stored contiguously.

* Actually given an implementation that uses the 'small string optimization' the data is contiguous, stored inside the string objects as long as it's small enough to fit. 'String0' is small enough for all the SSO implementations I know of. Once the data grows past what can be stored in-place the implementation moves it onto the heap.

The reason that modifying str1 does not affect the result of printing strArray[1] is that they are distinct objects with no relation, except that you initialized strArray[1] with the value of str1. This is just like doing:

int intArray[3];
int int0 = 0;
int int1 = 1;
int int2 = 2;

intArray[0] = int0;
intArray[1] = int1;
intArray[2] = int2;

int1 = 10000000; // does not modify intArray[1]

The idea here is that the usual behavior for objects in C++ is the same as for 'primitive types' or 'value types' you may be familiar with in other languages. It's possible to implement other behaviors in C++, but std::string is a regular type.

like image 165
bames53 Avatar answered Oct 06 '22 12:10

bames53


As barnes53 pointed out, the array of string only stores the string object, and can simply hold a pointer to the array of characters that represent the string.

The answer to the second question is that the array assignment is done by value rather than by reference, which implies that a copy of the string is made. That is why modifying the original string as no effect on the array version.

like image 20
merlin2011 Avatar answered Oct 06 '22 10:10

merlin2011


The array is contiguous the strings are not.

You say str1.resize(200, 'a'); which has no effect on the array because the array contains the value of what str1 used to be not the reference.

So the array value doesn't get overflowed because the value inside the array never changed.

like image 37
Jay Avatar answered Oct 06 '22 12:10

Jay