0

I was creating a vector of strings of size 4x4 with all characters as dots i.e. I was creating:

....
....
....
....

And then I had to push this vector of strings in a vector of vector of strings like in the code below:

int main()
{
    vector<vector<string>> ans;
    int n=4;
    vector<string> matrix(n);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            matrix[i][j]='.';    //inserting '.' as characters
        }
    }
    
    ans.push_back(matrix);
    
     for(int i=0;i<n;i++)   //printing the just inserted matrix
    {
        for(int j=0;j<n;j++)
        {
           cout<<ans[0][i][j]<<" ";
        }
        cout<<endl;
    }
    
}

This was when I am printing it back, it gives garbage/nothing. But, I change the insertion matrix[i][j]='.'; to matrix[i]+='.';, it is working fine.

int main()
{
    vector<vector<string>> ans;
    int n=4;
    vector<string> matrix(n);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            matrix[i]+='.';    //inserting '.' by +=
        }
    }
    
    ans.push_back(matrix);
    
     for(int i=0;i<n;i++)   //printing the just inserted matrix
    {
        for(int j=0;j<n;j++)
        {
           cout<<ans[0][i][j]<<" ";   //works fine
        }
        cout<<endl;
    }
    
}

What is the cause of this behaviour?

2 Answers2

3

I don't see how this doesn't crash outright:

vector<string> matrix(n);  // THIS IS A VECTOR OF EMPTY STRINGS

for(int i=0;i<n;i++)
{
    for(int j=0;j<n;j++)
    {
        matrix[i][j]='.';    //inserting '.' as characters
    }
}

When you reference matrix[i], you get back an empty string because you haven't assigned anything to that string. Attempting to access any element in that string and assigning a char to it is going to throw an exception be undefined behavior.

There's an easy fix:

for(int i=0;i<n;i++)
{
    matrix[i] = string(n ,' ');
    for(int j=0;j<n;j++)
    {
        matrix[i][j]='.';    //inserting '.' as characters
    }
}

Or simply:

for(int i=0;i<n;i++)
{
    matrix[i] = string(n ,'.');
}
selbie
  • 100,020
  • 15
  • 103
  • 173
  • Undefined behavior is undefined, it does not have to crash outright. :) – spectras Jul 10 '22 at 19:01
  • _"Attempting to access any element in that string and assigning a char to it is going to throw an exception."_ It's not: it's undefined behavior. – paolo Jul 10 '22 at 19:07
  • I'm actually surprised it's not guaranteed to throw an exception. But you are correct, it is UB. – selbie Jul 10 '22 at 19:07
  • @selbie You might be thinking about MSVC Debug builds. They range-check, I believe. – Paul Sanders Jul 10 '22 at 20:11
  • @PaulSanders - I'm booted into my Linux partition at the moment to validate what msvc does, but you are probably correct. – selbie Jul 10 '22 at 20:28
2

This code:

int n=4;
vector<string> matrix(n);

Will create a vector filled with n default-constructed strings; i.e. a vector with 4 empty strings. So, in the following loop, you're accessing each string with an out-of-bound index (which is undefined behavior):

for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
        matrix[i][j] = '.';
               // ^ Out of bounds: matrix[i].size() == 0
    }
}

In your second case:

for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
        matrix[i] += '.';
               // ^ You're appending '.' to the string.
               //   That's fine
    }
}

you're appending to the strings, which is fine.

If you want to have a vector of n strings, each containing n times character '.', you may just skip the loop and do:

int n = 4;
std::vector<std::string> matrix(n, std::string(n, '.'));

As a side note, you're not showing it but most probably you are:

using namespace std;

You shouldn't do it.

paolo
  • 2,345
  • 1
  • 3
  • 17
  • Thank you so much. Understood. Also, yes, was using 'using namespace std;' Could you please tell why I shouldn't use it? – Sneha Sharma Jul 10 '22 at 19:17
  • 1
    @SnehaSharma You're welcome. [This](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) is a thorough explanation to why you shouldn't do it. – paolo Jul 10 '22 at 19:20