Сопротивление экземпляров объектов, которые создаются внутри методов в C ++ - PullRequest
2 голосов
/ 12 декабря 2011

Допустим, у меня есть простой класс, который просто содержит объект:

class objholder{

    object ojb;
public:
    setobj(object o);
}

objholder::setobj(object o){
    obj = o;
}

objholder::getobj(){
    return obj;
}

Допустим, я создаю функцию, которая создает экземпляр object, который затем передается в objholder.

  • Что происходит с экземпляром object, когда функция возвращается?Это сохраняется?
  • Что произойдет, если я тогда попытаюсь получить доступ к экземпляру object, который был сохранен objholder, будет ли он содержать действительную ссылку?

Вот несколько простыхфункции, которые иллюстрируют функции, которые я описал выше.

void foo(objholder oh){
    object temp;
    oh.setobj(temp);

}
void bar(objholder oh){
    object temp = oh.getobj();
}

int main(int argc, char **argv){

    objholder o;

    foo(o);
    bar(o);
}

Ответы [ 3 ]

3 голосов
/ 13 декабря 2011

C ++ - это язык семантика значений , что означает, что по умолчанию типы обрабатываются как значения, копируются и т. Д., В отличие от Java или C #, которые имеют ссылочную семантику . Давайте проанализируем программу:

void foo( objholder );
int main(int argc, char **argv){
    objholder o;                 // [1]
    foo(o);                      // [2]
    bar(o);                      // [3]
}
void foo( objholder oh ) {       // [4]
    object tmp;                  // [5]
    oh.setobject( tmp );         // [6]
}                                // [7]

В [1] создается новый объект o в области действия main. Этот объект содержит подобъект obj типа object, инициализированный согласно objholder конструктору по умолчанию . В [2] копия этого объекта выполняется и передается в foo ([4]), который создает локальный object ([5]), который передается методу-члену setobject oh в [6], (помните: oh является копией objholder в main), потому что objholder::setobject принимает элемент по значению, создается копия tmp, и это копия передается в oh.setobject, которая, в свою очередь, делает копию и сохраняет ее в атрибуте member (не показан в коде). В [7] выполнение foo завершается, и все локальные переменные уничтожаются в обратном порядке создания, что означает, что tmp уничтожается, а затем oh (что, в свою очередь, означает, что внутренняя копия tmp уничтожен).

В этот момент мы вернулись в main, где наш локальный объект o остался нетронутым - все, что было обработано, было копией , переданной foo. Затем, как и при вызове foo, создается копия и передается bar.

Я начал замечать, что это связано с семантикой value в C ++ по сравнению с семантикой reference в других языках, таких как Java или C #. Если бы программа была (с синтаксисом в стороне) Java, в [2] и [3] была бы передана копия ссылки , и упомянутый объект как в main, foo и bar было бы то же самое. Это может быть достигнуто в C ++ с помощью указателей и ссылок. Ссылки на C ++ не просто похожи на ссылки на Java / C #, поэтому, если вы пришли из любого из этих языков, потребуется время, чтобы понять сходства и различия.

2 голосов
/ 12 декабря 2011

Что происходит с экземпляром object, когда функция возвращается?Это сохраняется?

Уничтожено вместе с держателем.Но обратите внимание, что objectholder копирует объект, переданный его setobj.

Что произойдет, если я тогда попытаюсь получить доступ к экземпляру object, который был сохраненobjholder будет ли он содержать действительную ссылку?

Вы имеете в виду ...

object obj;
{
    objectholder holder;
    holder.setobj(obj);
}
// do something to obj

?Ничего особенного не происходит (кроме случаев, когда object делает что-то особенное в конструкторе копирования).

1 голос
/ 13 декабря 2011

Как вы сделали свой объект, вы не «держите» объект, просто держите копию объекта.

это просто делает копию 'o' и сохраняет ее в 'obj'

objholder::setobj(object o)
{
    obj = o;
}

если вы хотите сохранить ссылку на объект, вам нужно либо передать ссылку или указатель на объект

object& obj;

objholder::setobj(object& o)
{
    obj = o;
}

, однако, сохраняя ссылку на объект, вы все ещене владелец объекта (если я правильно понял - это то, к чему вы стремитесь), вместо этого вам нужно будет использовать unique_ptr , чтобы стать владельцем объекта.Используя unique_ptr, вы можете как бы передавать объект.

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

...