в C ++, в чем разница между объектом и указателем на объект? - PullRequest
7 голосов
/ 21 марта 2011

В java и target-c переменная, представляющая объект, обычно является указателем на этот объект. Тем не менее, кажется, что в C ++ обычные типы указателей не содержат объектов. В чем разница между двумя?

Если я передаю структуру в качестве аргумента функции, я полагаю, что передаю по значению, что означает, что я фактически создаю новую структуру в памяти, и изменения в этой структуре внутри функции, которой она была передана, не будут влияет на структуру «source» вне функции. Однако, если я передам указатель на структуру, все равно останется только одна исходная структура, и изменения в структуре, на которую ссылается указатель, будут видны любому коду, который знает об этой структуре. Имею ли я это право?

Итак, есть ли разница с объектами? Когда я передаю объект без указателя в функцию, копируется ли весь объект?

Ответы [ 6 ]

15 голосов
/ 21 марта 2011

Это именно так, как вы сказали.

Когда вы передаете объект по значению, его конструктор копирования вызывается для создания нового экземпляра такого объекта, который будет использоваться внутри функции. Изменения, внесенные в такой новый объект, не будут отражены в исходном 1 .

Как и в случае со структурами, конструктор копирования по умолчанию просто делает поверхностную копию исходного объекта, то есть его поля копируются 2 в новый экземпляр; во многих случаях это нежелательно (например, если объект оборачивает указатель / другой ресурс), поэтому существуют классы, которые переопределяют конструктор копирования или полностью его отключают. Объекты этих последних классов могут передаваться только по указателю или по ссылке.

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

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

Это причина, по которой часто предпочитаемый метод передачи объектов - это const ссылка. Это дает несколько преимуществ:

  • копий не было; объект, который увидит вызывающий, будет точно тем, который указан в момент вызова;
  • невозможно внести изменения в исходный объект, благодаря квалификатору const;
  • если, однако, вызываемый объект должен изменить копию объекта, он все равно может создать копию самостоятельно из ссылки;
  • нет синтаксиса неуклюжего указателя;
  • полиморфизм сохранен, поскольку за кадром мы фактически передаем указатель;
  • нет больших сомнений относительно владения объектами: общее правило относительно ссылок заключается в том, что они принадлежат вызывающей стороне.
<ч />
  1. Что касается "необработанных полей" объекта; естественно, если исходный объект и копия продолжают совместно использовать указатель / дескриптор одного и того же ресурса, некоторые модификации одного могут повлиять на другой.

  2. Примитивные типы (и в общем случае POD) копируются по битам, в то время как конструктор копирования вызывается для типов, не относящихся к POD.

3 голосов
/ 21 марта 2011

Разница в основном связана с тем, где в памяти размещен объект. Например:

int main() {
    MyObject x;   //allocates space for an instance of MyObject on the stack
    MyObject* y;  //allocates space for a pointer on the stack
    MyObject* z = new MyObject();  //allocates space for a pointer on the 
                                   //stack and an object instance in the heap and
                                   //sets the pointer to point to the new instance
    MyObject* a = &x;  //allocates space for a pointer on the stack and 
                       //makes it point to 'x'
    ...
}

int someFunc(MyObject byValue, MyObject* byReference) {
   //the 'byValue' parameter will be passed by creating a copy of the 
   //entire source object on the stack (can be quite expensive for 
   //complex object types)

   //the 'byReference' parameter will be passed by creating a 
   //copy of the source pointer on the stack and setting it to 
   //point to the source object in memory
}
1 голос
/ 21 марта 2011

В C ++ переменная является переменной, которую она представляет. Это фактический объект в памяти, в фактическом местоположении.

Тем не менее, вы можете сделать так, чтобы такая переменная представляла указатель вместо этого, и в этом случае она скажет: «Эй, я - я, я указываю туда! . Да, там! Давай, иди туда! ".

Если вы явно не используете "ссылочный тип" C ++, который, как я подозреваю, нет, ВСЕ передаваемые аргументы являются значениями.

0 голосов
/ 21 марта 2011

У вас есть это право.

Действительно, вот как это работает. Указатель хранит адрес памяти переменной.

Когда вы передаете указатель (на объект) для функции в качестве параметра, это означает, что функция будет иметь доступ к этому объекту через свой адрес памяти вместо нового объекта, создаваемого в стеке.

Проверьте эту тему для получения дополнительной информации об указателях.

0 голосов
/ 21 марта 2011

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

Предпочтительныйчасто нужно передать константную ссылку, а не указатель или сам объект.

(Возможно, вы хотите знать, что на самом деле struct - это просто class, членами которого являются public по умолчанию, в частности, структуры также могут иметь определяемые пользователем конструкторы копирования. Структура не обязательно является просто инертными данными.)

0 голосов
/ 21 марта 2011

Ответы на вопросы во втором и третьем абзацах "да". В частности, если вы передадите объект функции по значению, функция получит копию этого объекта (созданную конструктором копирования).

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