Как передать объекты функциям в C++?

Я плохо знаком с программированием на C++, но у меня есть опыт в Java. Мне нужно руководство о том, как передать объекты функциям в C++.

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

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

245
задан Rakesh K 30 October 2010 в 19:53
поделиться

2 ответа

Правила для C++11:

Передайте на значение , за исключением случаев, когда

  1. вам не нужно владеть объектом, и вам потребуется простой псевдоним, и в этом случае вы переходите на const ссылку ,
  2. вы должны мутировать объект, В этом случае используйте pass by a non-const lvalue reference,
  3. вы передаете объекты производных классов в качестве базовых классов, и в этом случае вам необходимо pass by reference. (Используйте предыдущие правила для определения, следует ли передавать по ссылке const или нет).

Прохождение по указателю практически никогда не рекомендуется. Опциональные параметры лучше всего выразить в виде std::optional (boost::optional для более старых версий std libs), а наложение псевдонима прекрасно выполняется по ссылке. Семантика движения

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


Правила для C++03:

Передача аргументов по const reference, за исключением тех случаев, когда

  1. они должны быть изменены внутри функции, и такие изменения должны быть отражены снаружи, в этом случае вы передаёте по ссылкеconst
  2. без аргумента, функция должна быть вызываемой без аргумента, в этом случае вы передаёте по указателю, чтобы пользователи могли вместо этого передать NULL/0/nullptr; применить предыдущее правило, чтобы определить, следует ли передавать указатель на аргумент const
  3. , они имеют встроенные типы, которые могут быть переданы копией
  4. , они должны быть изменены внутри функции, и такие изменения должны , а не отражаться снаружи, В этом случае вы можете pass by copy (альтернативой будет передача по предыдущим правилам и создание копии внутри функции)

(здесь "pass by value" называется "pass by copy", потому что передача по значению всегда создает копию в C++03)


Есть еще кое-что, но эти несколько правил для новичков заставят вас зайти достаточно далеко.

269
ответ дан 23 November 2019 в 03:05
поделиться

Существуют некоторые различия в призвании конвенций в C ++ и Java. В C ++ используются технически говорящие только два конвенция: Pass-Value и Pass-Restain, причем некоторая литература, включающая в себя третью конвенцию Pass-By-Powner (которая фактически проходит по значению типа указателя). Кроме того, вы можете добавить Const-Ness к типу аргумента, повышая семантику.

Пасс по ссылке

Прохождение по ссылке означает, что функция будет концептуально примет экземпляр объекта и не копию ее. Ссылка концептуально псевдоним объектам, который использовался в контексте вызова и не может быть нулевым. Все операции, выполняемые внутри функции, применяются к объекту вне функции. Эта конвенция недоступна в Java или C.

pass по значению (и pass-by-указателю)

Компилятор будет генерировать копию объекта в контексте вызова и использовать эту копию внутри функции. Все операции, выполняемые внутри функции, выполняются к копии, а не внешним элементом. Это Конвенция для примитивных типов в Java.

Специальная версия ее передает указатель (адрес - объект) в функцию. Функция получает указатель, и любая и все операции, применяемые к самому указателю, применяются к копии (указатель), с другой стороны, операции, применяемые к разделушению указателя, будут применяться к экземпляру объекта в этом месте памяти, поэтому функция может иметь побочные эффекты. Эффект использования Pass-Value of указателя на объект позволит внутреннюю функцию изменять внешние значения, как с помощью передачи Pass-Researt, и также позволит дополнительным значениям (пройти нулевой указатель).

Это конвенция, используемая в C, когда функция должна модифицировать внешнюю переменную, а Конвенцию, используемую в Java со ссылками: ссылка скопирована, но указанный объект одинаково: изменения в ссылке / указатель Не видно вне функции, но изменения в заостренной памяти.

Добавление Const в уравнение

в C ++. Вы можете назначить постоянные значения на объекты при определении переменных, указателей и ссылок на разных уровнях. Вы можете объявить постоянную переменную, вы можете объявить ссылку на постоянный экземпляр, и вы можете определить все указатели на постоянные объекты, постоянные указатели на муравьевые объекты и постоянные указатели к постоянным элементам. И наоборот в Java, вы можете определить только один уровень константы (окончательное ключевое слово): что из переменной (экземпляра для примитивных типов, ссылка на ссылочные типы), но вы не можете определить ссылку на неизменный элемент (если сам класс не неизменный).

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

Правила большого пальца

Это некоторые основные правила для следующих правил:

  • предпочитают Pass-value для примитивных типов
  • Предполагают передачу от ссылок со ссылками на постоянные для других типов
  • , если Функция должна модифицировать аргумент. Использование Pass-by-Reference
  • Если аргумент является необязательным, используйте Pass-picker (постоянно, если необязательное значение не должно быть изменено)

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

Боковая заметка

Важно настаивать в важности разницы между ссылками C ++ и Java. В ссылках C ++ концептуально экземпляру объекта, а не доступа к нему. Самый простой пример реализует функцию свопа:

// C++
class Type; // defined somewhere before, with the appropriate operations
void swap( Type & a, Type & b ) {
   Type tmp = a;
   a = b;
   b = tmp;
}
int main() {
   Type a, b;
   Type old_a = a, old_b = b;
   swap( a, b );
   assert( a == old_b );
   assert( b == old_a ); 
}

Функция свопа выше изменяется как его аргументы благодаря использованию ссылок. Ближайший код в Java:

public class C {
   // ...
   public static void swap( C a, C b ) {
      C tmp = a;
      a = b;
      b = tmp;
   }
   public static void main( String args[] ) {
      C a = new C();
      C b = new C();
      C old_a = a;
      C old_b = b;
      swap( a, b ); 
      // a and b remain unchanged a==old_a, and b==old_b
   }
}

Версия кода Java изменит копии ссылок внутри, но не будет изменять фактические объекты снаружи. Ссылки Java представляют собой указатели C без арифметики указателя, который передается по значению в функции.

106
ответ дан 23 November 2019 в 03:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: