2013-10-27 2 views
0

Я новичок в C++, так что все еще узнаю о указателях и привык к их использованию.Сохранять объект и ссылку на объект, созданный внутри функции

Я объявил карту объекта, чтобы хранить объекты, к которым пользователь может получить доступ позже, используя ключ тега.

map<string,MyObject*> myMap; 

Объектами Я добавляю к MyMap создаются в функции, вызываемой моим основным

void myFunction(){ 
    ... 
    MyObject obj1(); 
    MyObject* objPtr; 
    objPtr = &obj1; 
    myMap.insert(pair<string,MyObject*>("xxxx", objPtr)); 
    ... 
    } 

Когда я исполняю эту функцию указатель на объект идеально вставляется в MyMap, но после выполнения функции Я теряю ссылку на obj1. Я думаю, потому что указатель и объект были локально созданы внутри функции, поэтому у меня все еще есть элемент «xxx» на карте, но с тем, что я считаю пустой ссылкой после.

Как сохранить объект и ссылку по всему миру? Я хотел создать этот объект в функции, так как он имеет некоторые переменные параметры, которые нужно получить от пользователя obj1 (m, n). Спасибо за любую помощь.

+2

Любая причина, по которой вы не можете хранить объекты на карте? Это значительно упростит ситуацию. – juanchopanza

+0

Почему бы вам не использовать 'objPtr = new MyObject();' вместо 'MyObject obj1(); objPtr = &obj1; '? Это создает объект в куче, где он переживает объем функции. Однако после завершения использования объектов и карты вам нужно удалить объекты. В вашем примере объект создается в стеке и удаляется после завершения функции. – MKroehnert

+0

Возможно, вам захочется узнать о ключевом слове 'new'. –

ответ

2

Если у вас есть веские основания сделать иначе, это может быть проще хранить объекты в карта:

map<string, MyObject> myMap; 

Тогда:

void myFunction(){ 
    ... 
    myMap.insert(std::make_pair("xxxx", MyObject())); 
    ... 
} 
+0

Я только что сделал, это устранило проблему ... Thansk – JLA

1

Вы можете динамически создавать объекты.

MyObject* objPtr = new MyObject; 

Но не забудьте удалить этот случай, когда вы не будете использовать его больше с

delete objPtr; 
+1

Вы должны быть осторожны с удалением только 'objPtr', поскольку он недействителен указатель, который хранится на карте. – MKroehnert

+0

Вы правы, это было естественно для меня. – Masadow

4

Код линия

MyObject obj1; 

определяет переменную локальной который содержит экземпляр MyObject. Когда контекст этой переменной будет оставлен, объект будет разрушен. Уничтожение объектов не означает, что указатели, указывающие на них, будут уведомлены каким-либо образом (например, они не установлены на 0), доступ к ним недействителен.

Вы в основном следующие параметры:

  • Создать объект на кучного вместо локально. Это делается с использованием ключевого слова new. Но тогда у вас есть delete объект в какой-то момент.

    MyObject *obj1 = new MyObject(arguments...); 
    
  • Так как это часто бывает трудно управлять, умные указатели где изобретены. Например, поскольку C++ 11 был добавлен shared_ptr (но он также доступен в некоторых компиляторах с предварительной версией C++ 0x). Этот тип умного указателя автоматически удалит объект для вас, когда последняя ссылка будет уничтожена.

    map<string,std::shared_ptr<MyObject>> myMap; // Note that I changed the type 
    
    std::shared_ptr<MyObject> obj1 = std::make_shared<MyObject>(arguments...); 
    myMap.insert(std::make_pair("xxxx", obj1)); 
    

    Кстати, я использовал std::make_pair, который будет автоматически deduce the template types for you.

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

    MyObject &obj = myMap["xxxx"]; // looking up the key 
    obj.doSomeAction();   // modify it; no need to re-insert 
    

    Ссылки ведут себя подобно указателям (то есть они только «точка на» какой-то, например), но есть некоторые различия. Например, ссылки всегда указывают на один и тот же экземпляр на протяжении их жизни (вы не можете переназначить ссылки). Кроме того, их синтаксис равен значениям, т. Е. Нет ->.

Лично я бы предпочел третий вариант, если вам не нужно указывать указатели на один и тот же объект в нескольких местах вашей программы. Если это так, мы говорим об «общих» объектах, которые в точности соответствуют тому, где вы хотите использовать «общие» указатели. Первый вариант очень низкоуровневый и должен считаться «устаревшим».

+0

+1 для использования 'shared_ptr', но могли бы вы указать, что это доступно только по последнему стандарту? – MKroehnert

+1

@MKroehnert Спасибо, я добавил комментарий. – leemes

+0

Огромное спасибо вам, что только объект хранения вместо указателей исправил все проблемы ... и ваше объяснение было очень полезным – JLA

Смежные вопросы