Почему моя структура теряет строковое значение даже со ссылками? - PullRequest
0 голосов
/ 13 июня 2019
struct Word {

    string wordName; //loses its value
    vector<string> contents; //irrelevant for the question
    int numContents = 0; //maintains its value

};

vector<Word*> wordMsgs;

int main()
{

vector<string> result;
result.push_back("wordName");
result.push_back("shouldEnterIf");

Word curr;
        //New Word
        if (result[1] != "") {
            Word w;
            w.numContents = 10; //just a testing #, suppose to represent size of vector
            wordMsgs.push_back(&w);


            w.wordName = result[0]; //name of Word


            //here w.wordName and (*wordMsgs[0]).wordName display the same string; result[0] 
            curr = w;
        }
        //here curr.wordName displays result[0] but (*wordMsgs[0]).wordName doesn't. However, (*wordMsgs[0]).numContents returns 10 as expected
}
}

Итак, у меня есть вектор структурных ссылок, предполагая, что метод push_back () для векторов только выдвигает копию в конец вектора.Я создаю экземпляр моей структуры Word и помещаю эту ссылку в мой вектор, wordMsgs.Затем я редактирую структуру, на которую он указывает, и затем моя строковая переменная теряется при выходе из оператора if!Однако моя переменная int никогда не теряет своего значения.Я не понимаю, потому что я использовал указатели (и я на C ++, поэтому я думал, что строки были в порядке), и я не думаю, что это проблема локальной переменной ...

Ответы [ 3 ]

1 голос
/ 13 июня 2019

Переменная w in:

    if (...) {
        Word w;
        wordMsgs.push_back(&w);
        ...
    }

Распределяется в стеке внутри области действия оператора if.

Затем вы добавляете его адрес в свой векторpointers.

Вне оператора if эта переменная освобождается, и значение по этому адресу больше не является "сплошным", поэтому в этом векторе у вас фактически есть "адрес мусора".

С этого момента поведение вашей программы в основном непредсказуемо ...

0 голосов
/ 13 июня 2019

У вас есть вектор указателей, а не ссылок.Когда вы возвращаете адрес локально определенной структуры Wors w с помощью &w, вы потеряете эти данные непосредственно, когда выйдете из оператора if.Вам нужно выделить и освободить память для вектора.Лучше всего просто толкать объекты в векторе или использовать умный указатель.

0 голосов
/ 13 июня 2019

Вот минимальный пример того, что идет не так в вашем коде:

#include <string>
#include <vector>
#include <iostream>

int main() {
   std::vector<string*> words;     // why pointers?

   if (true) {                    // scope starts here
       std::string word = "muh";   
       words.push_back(&word);    // dont do that !!
   }                              // scope ends here

   std::cout << *words.back(); 
}

К тому времени, когда вы обращаетесь к строке путем разыменования указателя, строка давно исчезла, потому что word уничтоженокогда это выходит за рамки.Разыменование указателя: неопределенное поведение .Вы не должны иметь необработанные указатели в векторе, когда вам это не нужно.Вы, вероятно, хотели что-то вроде этого:

#include <string>
#include <vector>
#include <iostream>

int main() {
   std::vector<string> words;

   if (true) {               
       std::string word = "muh";   
       words.push_back(word);      // vector stores a copy ! and manages lifetime of its elements
   }                         

   std::cout << words.back(); 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...