C++: Array within Tuple within Vector gets replaced with last entered

Here is a Minimal Reproducible Example:

#include <iostream>
#include <vector>
#include <tuple>
using namespace std;


int main() {

    vector<tuple<char *, int, int>> test;
    cout << "During Loop:" << endl;
    for (int i = 0; i < 4; i++) {
        char letters[3];
        int firstNumber = i;
        int secondNumber = 4 - i;
        switch (i) {
        case 0:
            letters[0] = 'a';
            letters[1] = 'b';
            letters[2] = 'c';
            break;
        case 1:
            letters[0] = 'd';
            letters[1] = 'e';
            letters[2] = 'f';
            break;
        case 2:
            letters[0] = 'g';
            letters[1] = 'h';
            letters[2] = 'i';
            break;
        case 3:
            letters[0] = 'j';
            letters[1] = 'k';
            letters[2] = 'l';
            break;
        }
        tuple<char *, int, int> toPlace = make_tuple(letters, firstNumber, secondNumber);
        test.emplace_back(toPlace);
        for (int j = 0; j < 3; j++) {
            cout << get<0>(toPlace)[j];
        }
        cout << " " << firstNumber << " " << secondNumber << endl;
    }

    cout << endl << "After Loop: " << endl;

    for (int k = 0; k < 4; k++) {
        for (int l = 0; l < 3; l++) {
            cout << get<0>(test[k])[l];
        }
        cout << " " << get<1>(test[k]) << " " << get<2>(test[k]) << endl;
    }

    return 0;
}

This is the output:

During Loop:
abc 0 4
def 1 3
ghi 2 2
jkl 3 1

After Loop:
jkl 0 4
jkl 1 3
jkl 2 2
jkl 3 1

So why do the arrays within the tuple all become ‘jkl’, whilst the numbers do not change? (Using a string doesn’t have this issue I know I could just use that, but I’m curious as to why this happens, as it also happens if the array is of type int).

I’m assuming it is because when making the tuple, its passing by reference into that make_tuple function and that points to the ‘letters’ array which get changed each loop. If so how would I rewrite this so an Array value could be stored in the Tuple rather than the pointer each time?

TL;DR:
I tried to store a vector of tuples in which one is an array, by entering the tuples through a loop. During the loop it store the correct char array, and I was expecting the tuple would keep the value of the char array as it was entered. However it ends up replacing each char array with the last one entered, as it is actually a pointer that has been entered.

  • 4

    You don’t create copies of the string. All pointers will point to the same array, which will contain the last thing you set it to.

    – 

  • 6

    And what’s worse, because this array is local inside the loop, its life-time will end each iteration of the loop, and you will save a pointer that will become immediately invalid.

    – 

  • 1

    Also using std::tuple outside (meta) template programming is hardly ever needed. Better to declare a custom struct of your own. struct my_data { std::string name; int value1; int value2; }. You will end up with better readable code. Another option is to use std::array<char,3>

    – 




  • 2

    a char* is a pointer. A pointer is not an array. A char* is not a string. Use std::string

    – 




  • 2

    In this particular code you probably want to replace char* with std::array<char,3> – since its not an actual string

    – 

Leave a Comment