Что означает `* &` в объявлении функции?

Я написал функцию по строкам:

void myFunc(myStruct *&out) {
    out = new myStruct;
    out->field1 = 1;
    out->field2 = 2;
}

Теперь в вызывающей функции я могу написать что-то вроде этого:

myStruct *data;
myFunc(data);

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

Может ли кто-нибудь объяснить мне, что на самом деле делает этот *&? Это выглядит странно, и я просто не могу этого толковать.

Ответы

Ответ 1

Символ и символ в объявлении переменной С++ означает reference.

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

Итак, чтобы повторить, "действующий символ" здесь не *&, эта комбинация сама по себе не означает много. * является частью типа myStruct *, то есть "указатель на myStruct", а & делает его ссылкой, поэтому вы читаете его как "out является ссылкой на указатель на myStruct".

Оригинальный программист мог бы, на мой взгляд, помочь, написав его как:

void myFunc(myStruct * &out)

или даже (не мой личный стиль, но, конечно, все еще действителен):

void myFunc(myStruct* &out)

Конечно, есть много других мнений о стиле.:)

Ответ 2

В C и С++ и означает вызов по ссылке; вы позволяете функции изменять переменную. В этом случае ваша переменная является указателем на тип myStruct. В этом случае функция выделяет новый блок памяти и присваивает это вашему указателю "данные".

В прошлом (скажем, K & R) это должно было быть сделано путем передачи указателя, в данном случае указателя на указатель или **. Оператор ссылки позволяет считывать более читаемый код и более надежную проверку типов.

Ответ 3

Похоже, вы перепроектируете конструктор!

Почему бы просто не создать соответствующий конструктор?
Обратите внимание, что в С++ структура похожа на класс (он может иметь конструктор).

struct myStruct
{
    myStruct()
        :field1(1)
        ,field2(2)
    {}
};

myStruct*  data1 = new myStruct;

// or Preferably use a smart pointer
std::auto_ptr<myStruct>   data2(new myStruct);

// or a normal object
myStruct    data3;

Ответ 4

Возможно, стоит объяснить, почему это не &*, но наоборот. Причина в том, что объявления создаются рекурсивно, и поэтому ссылка на указатель строится, например,

& out // reference to ...
* (& out) // reference to pointer

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

* out // pointer to ...
& (* out) // pointer to reference

Указатель ссылки не является законным. Поэтому порядок *&, что означает "ссылка на указатель".

Ответ 5

Как и другие, и означает, что вы ссылаетесь на действительную переменную в функцию, а не на ее копию. Это означает, что любые изменения, внесенные в переменную в функции, влияют на исходную переменную. Это может стать особенно запутанным, когда вы передаете указатель, который уже является ссылкой на что-то еще. В случае, если ваша подпись функции выглядела так:

void myFunc(myStruct *out);

Что произойдет, так это то, что вашей функции будет передана копия указателя для работы. Это означает, что указатель указывает на одно и то же, но будет другой переменной. Здесь любые изменения, сделанные в *out (т.е. Какие точки в точке) были бы постоянными, но изменения, сделанные в out (сам указатель), будут применяться только в myFunc. С такой подписью

void myFunc(myStruct *&out);

Вы объявляете, что функция будет ссылаться на исходный указатель. Теперь любые изменения, внесенные в переменную-указатель out, будут влиять на исходный указатель, который был передан.

При этом линия

out = new myStruct;

изменяет переменную указателя out, а не *out. Независимо от того, что out используется для указания, все еще жив и здоров, но теперь новый кусок myStruct был создан в куче, а out был изменен, чтобы указать на него.

Ответ 7

В С++ это ссылка на указатель, эквивалентная указателю на указатель на C, поэтому аргумент функции присваивается.

Ответ 8

Как и в большинстве типов данных в С++, вы можете прочитать его справа налево, и это будет иметь смысл.

myStruct *&out

out является ссылкой (&) на указатель (*) на объект myStruct. Это должно быть ссылкой, потому что вы хотите изменить то, что указывает out (в данном случае a new myStruct).

Ответ 9

MyClass * & MyObject

Здесь MyObject является ссылкой на указатель MyClass. Поэтому вызов myFunction (MyClass * & MyObject) является вызовом по ссылке, мы можем изменить MyObject, который ссылается на указатель. Но если мы делаем myFunction (MyClass * MyObject), мы не можем изменить MyObject, потому что это вызов по значению, он просто скопирует адрес во временную переменную, чтобы мы могли изменить значение, где MyObject является Pointing, но не MyObject.

поэтому в этом случае писатель сначала назначает новое значение, из-за чего требуется вызов по ссылке.