инициализация ints против инициализации строк с помощью указателей, c ++

0

Недавно я столкнулся с проблемой, экспериментируя со связанными списками. Когда я использую функцию для связывания нового узла, который имеет строку в своем поле данных, он не работает. Под этим я подразумеваю, что когда функция (linkin(), см. Ниже) возвращается, строка (которая была локальной для функции) уничтожается, и поэтому поле строки кажется неинициализированным.

Однако, когда я делаю эту ту же операцию с int, похоже, все работает нормально. Код, который я использовал, ниже (его версия int, но сделайте val вместо строки int, чтобы увидеть другую версию). Может ли кто-нибудь объяснить мне, что происходит?

Благодарю!

struct testlist {
    int val;
    testlist *next;
};
void linkin ( testlist *a );

int main() {

    testlist test;

    linkin(&test);
    cout << test.next->val <<endl;
}


void linkin ( testlist *a )
{
  testlist b;
  b.val=1;
  a->next = &b;
  cout << a->next->val <<endl;
}
  • 2
    О, хорошо, спасибо за то, что показали нам работающий код и скрыли тот, который сломан. Конечно, мы можем догадаться, что не так с кодом, который мы не видели, посмотрев на другой работающий код.
  • 0
    Когда вы говорите string, вы имеете в виду std :: string или char *?
Показать ещё 8 комментариев
Теги:
pointers

2 ответа

4
Лучший ответ
testlist b;
a->next = &b;

a->next указывает на локальный временный объект, который будет уничтожен сразу после возврата из функции. Он вызывает неопределенное поведение после разыменования его из функции.

Это неопределенное поведение, иногда это работает, иногда нет.


Также в C++ есть связанный список: std::list. С другой стороны, вы можете использовать интеллектуальные указатели, такие как std::unique_ptr вместо std::unique_ptr указателей. Я написал смарт-указатель, основанный на вашем контейнере:

struct List
{
    int val;
    unique_ptr<List> next;
};

void linkin (List &a)
{
    unique_ptr<List> b(new List);
    b->val = 1;
    a.next = move(b); // After move you can't use b anymore
    cout << a.next->val << endl;
}

int main()
{
    List test;
    linkin(test);
    cout << test.next->val <<endl;
}
0

Сразу, в linkin() я могу видеть, что вы храните указатель в на объект, который собирается выходить за рамки - то есть: быть уничтожены. a

Есть причины, по которым это может показаться работающим с int, но не сложным типом, как std :: string. Несмотря на внешность, это сломанный код - попробуйте переписать linkin():

void linkin ( testlist& a )
{
   testlist* b = new testlist;
   b->val=1;
   a->next = b;
   cout << a->next->val <<endl;
}    
  • 0
    Не уверен, что использование new без умного указателя - действительно хороший совет!
  • 0
    @ g-makulik Вы просто, абсолютно, категорически, принципиально, не можете быть чертовски серьезными.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню