2016-06-09 5 views
1

В этом обсуждении What and where are the stack and heap? Я узнал, что типы значений хранятся в стеке и указатели на куче. В моем приложении у меня есть некоторые QList<T*> и QMap<QString,QList<QString>>, содержащие указатели некоторых объектов.Сохранение ссылочных типов в типизированном списке значений?

Теперь я знаю, что ссылочные типы хранятся в куче (приложении). Но мои списки, содержащие эти ссылки, являются типами значений, и поэтому они находятся в стеке. Они доступны только в потоке, в котором они были созданы. Но откуда я знаю, когда поток будет мертв, или если функция/метод, которую я вызываю, находится в другом потоке? Мне нужны списки во всем приложении. Это немного глупый вопрос, но я заполняю свои списки, и это простой шанс, если объекты доступны.

EDIT:

@ coyotte508

Единственное, что в стеке указатели члены, указывающие, что памяти. Иными словами, если они были созданы в стеке, то есть только , если они являются локальными переменными функции или другого класса, объявленного в стеке.

В моем главном классе у меня есть список: QList<Fachbereich *> lFBs;

В конструктор моего основного класса я создаю список:

lFBs=QList<Fachbereich *>(); 

..- Тогда я вызываю метод ReadConfig();

Одна из подпрограмм:

void AppConfig::ReadFachbereiche(QXmlStreamReader &reader) 
{ 
    Fachbereich* fb(0); 
    while(!reader.atEnd()) 
    { 
     reader.readNext(); 
     if (reader.error()) 
     { 
      bla bla 

     } 
     else 
     { 
      if (reader.isStartElement()) 
      { 
       if (reader.name().toString().toLower() == "fb") 
       { 
        QString sFB=""; 

        try{ sFB=reader.attributes().value("name").toString();} 
        catch(...){} 

        if (sFB !="") 
        { 
         fb=new Fachbereich(); 
         fb->Name=sFB; 
        } 
       } 
       else if (reader.name().toString().toLower() == "stddir") 
       { 
        if (fb!=0) fb->stdDir=reader.readElementText().replace("\\", "/").toLower(); 
       } 
      } 
      else if (reader.isEndElement()) 
      { 
       if (reader.name().toString().toLower() == "fb") 
       { 
        if (fb!=0){ 
         if (!lFBs.contains(fb)) 
          lFBs.append(fb); 
        } 
       } 
       else if (reader.name().toString().toLower() == "fachbereiche") return; 
      } 
     } 
    } 
} 

Таким образом, fb является локальной переменной этой функции. Я думал, создав объект с new, память будет выделена в куче, но это не так. Новый, созданный, к моим спискам возвращаемых ссылочных типов исчезает при выходе из функции.

Должен ли я хранить объекты в QSharedPointer? Ст. как это?

QList<QSharedPointer> lFBs; 

...

QSharedPointer<Fachbereich> fb= QSharedPointer<Fachbereich>(new Fachbereich); 

ответ

0

Ваш код не имеет много общего с нитками.

Вы хотите сохранить переменную fb вне функции.

И вы добавляете его в список, что хорошо.

if (reader.name().toString().toLower() == "fb") 
{ 
    if (fb!=0){ 
     if (!lFBs.contains(fb)) 
      lFBs.append(fb); 
    } 
} 
else if (reader.name().toString().toLower() == "fachbereiche") return; 

Но делать это только в некоторых случаях, а иногда (когда название «fachbereiche») вы сразу вернуться. Я не думаю, что вам нужно даже поместить его в указатель. QList<Fachbereich> сохраняет данные, и поскольку он является членом вашего класса, данные будут сохранены до тех пор, пока ваш класс не будет уничтожен.

Что бы я сделал:

  • Прекратите использование указателей или new. Это зависит от того, как создается Fachbereich, но он не должен создавать проблем
  • Убедитесь, что элемент всегда добавлен в список, если это необходимо.

Для этого в начале функции:

Fachbereich fb; 
bool somethingRead = false; 

При принятии решения о "создании" fb, просто установить логическое значение истина:

if (sFB !="") 
{ 
    /* Maybe add a debugging message here to say it was created */ 
    somethingRead = true; 
    fb.Name=sFB; 
} 

Заменить этот код:

  if (reader.name().toString().toLower() == "fb") 
      { 
       if (fb!=0){ 
        if (!lFBs.contains(fb)) 
         lFBs.append(fb); 
       } 
      } 
      else if (reader.name().toString().toLower() == "fachbereiche") return; 

by:

break; //leave the loop 

И, наконец, в конце функции, после цикла:

/* The boolean is true if fb was initialized */ 
if (somethingRead) { 
    lFb.push_back(fb); 
} 

Тогда после того, как функция была вызвана, lFb.size() вашего класса должен быть больше 0 и lFb.last() должен содержать ваш элемент ,

QList внутренне сохраняет объект после выделения их new, поэтому вам не нужно беспокоиться об этом.

+0

Большое спасибо за внимание к моей проблеме. Подумайте, я использовал ссылочные типы, потому что я хочу знать, если объекты инициализированы. Теперь я принимаю ваш совет, и он отлично работает :) –