Передача аргументов по значению
Аргументы могут передаваться по значению (by value) и по ссылке (by reference).
При передаче аргументов по значению внешний объект, который передается в качестве аргумента в функцию, не может быть изменен в этой функции.
В функцию передается само значение этого объекта. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <iostream>void square(int, int);int main(){ int a = 4; int b = 5; std::cout << "Before square: a = " << a << "\tb=" << b << std::endl; square(a, b); std::cout << "After square: a = " << a << "\tb=" << b << std::endl; return 0;}void square(int a, int b){ a = a * a; b = b * b; std::cout << "In square: a = " << a << "\tb=" << b << std::endl;} |
Функция square принимает два числа и возводит их в квадрат. В функции main перед и после выполнения функции square происходит вывод на консоль значений переменных a и b, которые передаются в square в качестве аргументов.
И при выполнении мы увидим, что изменения аргументов в функции square действуют только в рамках этой функции. Вне ее значения переменных a и b остаются неизменными:
Before square: a = 4 b = 5 In square: a = 16 b = 25 After square: a = 4 b = 5
Почему так происходит? При компиляции функции для ее параметров выделяются отдельные участки памяти. При вызове функции вычисляются значения аргументов, которые передаются на место параметров. И затем значения аргументов заносятся в эти участки памяти. То есть функция манипулирует копиями значений объектов, а не самими объектами.
void Method(ref int refArgument)
{
refArgument = refArgument + 44;
}
int number = 1;
Method(ref number);
Console.WriteLine(number);
// Output: 45Передача параметров по ссылке
При передаче параметров по ссылке передается ссылка на объект, через которую мы можем манипулировать самим объектов, а не просто его значением. Так, перепишем предыдущий пример, используя передачу по ссылке:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <iostream>void square(int&, int&);int main(){ int a = 4; int b = 5; std::cout << "Before square: a = " << a << "\tb=" << b << std::endl; square(a, b); std::cout << "After square: a = " << a << "\tb=" << b << std::endl; return 0;}void square(int &a, int &b){ a = a * a; b = b * b; std::cout << "In square: a = " << a << "\tb=" << b << std::endl;} |
Теперь параметры a и b передаются по ссылке. Ссылочный параметр связывается непосредственно с объектом, поэтому через ссылку можно менять сам объект.
И если мы скомпилируем и запустим программу, то результат будет иным:
Before square: a = 4 b = 5 In square: a = 16 b = 25 After square: a = 16 b = 25
Передача по ссылке позволяет возвратить из функции сразу несколько значений. Также передача параметров по ссылке является более эффективной при передаче очень больших объектов. Поскольку в этом случае не происходит копирования значений, а функция использует сам объект, а не его значение.
От передачи аргументов по ссылке следует отличать передачу ссылок в качестве аргументов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <iostream>void square(int, int);int main(){ int a = 4; int b = 5; int &aRef = a; int &bRef = b; std::cout << "Before square: a = " << a << "\tb=" << b << std::endl; square(aRef, bRef); std::cout << "After square: a = " << a << "\tb=" << b << std::endl; return 0;}void square(int a, int b){ a = a * a; b = b * b; std::cout << "In square: a = " << a << "\tb=" << b << std::endl;} |
Если функция принимает аргументы по значению, то изменение параметров внутри функции также никак не скажется на внешних объектах, даже если при вызове функции в нее передаются ссылки на объекты.
Before square: a = 4 b = 5 In square: a = 16 b = 25 After square: a = 4 b = 5
Передача параметров по значению больше подходит для передачи в функцию небольших объектов, значения которых копируются в определенные участки памяти, которые потом использует функция.
Передача параметров по ссылке больше подходит для передачи в функцию больших объектов, в этом случае не нужно копировать все содержимое объекта в участок памяти, за счет чего увеличивается производительность программы.
Передача аргументов по ссылке. Пример
В предыдущих примерах типы значений передаются по ссылке.
Также можно использовать ключевое слово ref для передачи ссылочных типов по ссылке.
Ссылочный тип, иногда называемый псевдонимом, служит для задания объекту дополнительного имени. Ссылка позволяет косвенно манипулировать объектом, точно так же, как это делается с помощью указателя. Однако эта косвенная манипуляция не требует специального синтаксиса, необходимого для указателей.
Передача ссылочного типа по ссылке позволяет вызываемому методу заменять объект, на который указывает ссылочный параметр в вызывающем объекте. Место хранения объекта передается методу в качестве значения ссылочного параметра. Если изменить место хранения параметра (с указанием на новый объект), необходимо изменить место хранения, на который ссылается вызывающий объект. В следующем примере экземпляр ссылочного типа передается как параметр ref.
class Product
{
public Product(string name, int newID)
{
ItemName = name;
ItemID = newID;
}
public string ItemName { get; set; }
public int ItemID { get; set; }
}
private static void ChangeByReference(ref Product itemRef)
{
// Change the address that is stored in the itemRef parameter.
itemRef = new Product("Stapler", 99999);
// You can change the value of one of the properties of
// itemRef. The change happens to item in Main as well.
itemRef.ItemID = 12345;
}
private static void ModifyProductsByReference()
{
// Declare an instance of Product and display its initial values.
Product item = new Product("Fasteners", 54321);
System.Console.WriteLine("Original values in Main. Name: {0}, ID: {1}\n",
item.ItemName, item.ItemID);
// Pass the product instance to ChangeByReference.
ChangeByReference(ref item);
System.Console.WriteLine("Back in Main. Name: {0}, ID: {1}\n",
item.ItemName, item.ItemID);
}
// This method displays the following output:
// Original values in Main. Name: Fasteners, ID: 54321
// Back in Main. Name: Stapler, ID: 12345
Дополнительные сведения о передаче ссылочных типов по значению и по ссылке см. в разделе Передача параметров ссылочного типа.
Комментариев нет:
Отправить комментарий