Передача ссылкой или передача значением? [закрытый]

2D-массив в основном представляет собой 1D-массив указателей, где каждый указатель указывает на 1D-массив, который будет содержать фактические данные.

Здесь N - строка, а M - столбец.

динамическое распределение

int** ary = new int*[N];
  for(int i = 0; i < N; i++)
      ary[i] = new int[M];

fill

for(int i = 0; i < N; i++)
    for(int j = 0; j < M; j++)
      ary[i][j] = i;

print

for(int i = 0; i < N; i++)
    for(int j = 0; j < M; j++)
      std::cout << ary[i][j] << "\n";

бесплатно

for(int i = 0; i < N; i++)
    delete [] ary[i];

или

delete [] ary;
51
задан 8 revs, 4 users 65% 20 July 2014 в 22:52
поделиться

8 ответов

Вот мой собственный вклад для язык программирования Java .

сначала некоторый код:

public void swap(int x, int y)
{
  int tmp = x;
  x = y;
  y = tmp;
}

вызов этого метода приведет к этому:

int pi = 3;
int everything = 42;

swap(pi, everything);

System.out.println("pi: " + pi);
System.out.println("everything: " + everything);

"Output:
pi: 3
everything: 42"

даже использующие 'реальные' объекты покажут подобный результат:

public class MyObj {
    private String msg;
    private int number;

    //getters and setters
    public String getMsg() {
        return this.msg;
    }


    public void setMsg(String msg) {
        this.msg = msg;
    }


    public int getNumber() {
        return this.number;
    }


    public void setNumber(int number) {
        this.number = number;
    }

    //constructor
    public MyObj(String msg, int number) {
        setMsg(msg);
        setNumber(number);
    }
}

public static void swap(MyObj x, MyObj y)
{
    MyObj tmp = x;
    x = y;
    y = tmp;
}

public static void main(String args[]) {
    MyObj x = new MyObj("Hello world", 1);
    MyObj y = new MyObj("Goodbye Cruel World", -1); 

    swap(x, y);

    System.out.println(x.getMsg() + " -- "+  x.getNumber());
    System.out.println(y.getMsg() + " -- "+  y.getNumber());
}


"Output:
Hello world -- 1
Goodbye Cruel World -- -1"

таким образом ясно, что Java передает свои параметры значением как значение для [1 115] пи и все и , объекты MyObj не подкачиваются. знайте, что "значением" только путь в Java для передачи параметров методу. (например, язык как C++ позволяет разработчику передавать параметр ссылкой с помощью' & ' после типа параметра)

теперь хитрая часть , или по крайней мере часть, которая смутит большинство новых Java-разработчиков: (одолженный от javaworld)
Исходный автор: Tony Sintes

public void tricky(Point arg1, Point arg2)
{
    arg1.x = 100;
    arg1.y = 100;
    Point temp = arg1;
    arg1 = arg2;
    arg2 = temp;
}
public static void main(String [] args)
{
    Point pnt1 = new Point(0,0);
    Point pnt2 = new Point(0,0);
    System.out.println("X: " + pnt1.x + " Y: " +pnt1.y); 
    System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
    System.out.println(" ");
    tricky(pnt1,pnt2);
    System.out.println("X: " + pnt1.x + " Y:" + pnt1.y); 
    System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);  
}


"Output
X: 0 Y: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0"

хитрый успешно изменения значение pnt1! Это подразумевало бы, что Объекты передаются ссылкой, дело обстоит не так! Корректный оператор был бы: эти Ссылки на объект передаются значением.

[еще 1138] от Tony Sintes:

метод успешно изменяет значение pnt1, даже при том, что это передается значением; однако, подкачка pnt1 и сбоев pnt2! Это - основной источник беспорядка. В основном () метод, pnt1 и pnt2 является не чем иным как ссылками на объект. При передаче pnt1 и pnt2 к хитрому () метод Java передает ссылки значением точно так же, как любой другой параметр. Это означает, что ссылки, переданные методу, являются на самом деле копиями исходных ссылок. Рисунок 1 ниже показывает две ссылки, указывающие на тот же объект после того, как Java передаст объект методу.

figure 1
(источник: javaworld.com )

Заключение или длинная короткая история:

  • Java передает его, параметры значением
  • "значением" только путь в Java для передачи параметра методу
  • использование , методы от объекта данный как параметр изменятся объект, поскольку ссылки указывают на исходные объекты. (если тот метод сам изменяет некоторые значения)

полезные ссылки:

31
ответ дан Glorfindel 7 November 2019 в 10:06
поделиться

Вот другая статья для c# язык программирования

, c# передает свои аргументы значением (по умолчанию)

private void swap(string a, string b) {
  string tmp = a;
  a = b;
  b = tmp;
}

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

string x = "foo";
string y = "bar";
swap(x, y);

"output: 
x: foo
y: bar"

однако, в отличие от java c# делает , дают разработчику возможность передать параметры ссылкой , это сделано при помощи 'касательно' ключевого слова перед типом параметра:

private void swap(ref string a, ref string b) {
  string tmp = a;
  a = b;
  b = tmp;
} 

эта подкачка будет изменять значение параметра, на который ссылаются:

string x = "foo";
string y = "bar";
swap(x, y);

"output: 
x: bar
y: foo"

c# также имеет ключевое слово и различие между касательно и является тонким. из MSDN:

вызывающая сторона метода, который берет параметр , не обязана присваивать переменной, переданной как параметр до вызова; однако, вызываемый требуется присвоиться к параметр перед возвратом.

и

На контрасте касательно параметров , считал первоначально присвоенным вызываемым. По сути, вызываемый не требуется присвоиться к касательно [1 116] параметр перед использованием. Касательно параметров передаются и в и из метода.

маленькая ловушка, как в Java, это , объекты, переданные значением, могут все еще быть изменены с помощью их внутренних методов

заключение:

  • c# передает свои параметры, по умолчанию, значением
  • , но когда необходимые параметры смогут также быть переданы ссылкой использование касательно ключевого слова
  • , внутренние методы от параметра, переданного значением , изменятся объект (если тот метод сам изменит некоторые значения)

полезные ссылки:

20
ответ дан Community 7 November 2019 в 10:06
поделиться

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

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

>>> def do_something(a, b):
...     a = "Red"
...     b.append("Blue")
... 
>>> a = "Yellow"
>>> b = ["Black", "Burgundy"]
>>> do_something(a, b)
>>> print a, b
Yellow ['Black', 'Burgundy', 'Blue']

строка a = "Red" просто создает локальное имя, a, для строкового значения "Red" и не имеет никакого эффекта на переданный - в аргументе (который теперь скрыт, поскольку a должен относиться к локальному имени с тех пор). Присвоение не является оперативной операцией, независимо от того, изменяем ли аргумент или неизменен.

b параметр является ссылкой на изменяемый объект списка, и .append(), метод выполняет оперативное расширение списка, лавирующего на новом "Blue" строковое значение.

(Поскольку строковые объекты неизменны, у них нет методов, которые поддерживают оперативные модификации.)

, Как только функция возвращается, переназначение [1 110] не имело никакого эффекта, в то время как расширение [1 111] ясно показывает семантику вызова передачи стилем ссылки.

, Как упомянуто прежде, даже если аргументом в пользу [1 112] является изменяемый тип, переназначение в функции не является оперативной операцией, и таким образом, не было бы никакого изменения в значении передаваемого аргумента:

>>> a = ["Purple", "Violet"]
>>> do_something(a, b)
>>> print a, b
['Purple', 'Violet'] ['Black', 'Burgundy', 'Blue', 'Blue']

, Если бы Вы не хотели свой список, измененный вызванной функцией, Вы вместо этого использовали бы неизменный тип "кортеж" (определенный круглыми скобками в литеральной форме, а не квадратными скобками), который не поддерживает оперативное .append() метод:

>>> a = "Yellow"
>>> b = ("Black", "Burgundy")
>>> do_something(a, b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in do_something
AttributeError: 'tuple' object has no attribute 'append'
19
ответ дан yukondude 7 November 2019 в 10:06
поделиться

Существует хорошее объяснение здесь для.NET.

Много людей является удивлением, что ссылочные объекты на самом деле передаются значением (и в C# и в Java). Это - копия адреса стека. Это препятствует тому, чтобы метод изменился, где объект на самом деле указывает на, но все еще позволяет методу изменять значения объекта. В C# его возможное для передачи ссылки ссылкой что означает, можно измениться, где фактический объект указывает на.

6
ответ дан Karl Seguin 7 November 2019 в 10:06
поделиться

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

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

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

5
ответ дан Matthew Schinckel 7 November 2019 в 10:06
поделиться

значением

  • медленнее, чем ссылкой, так как система должна скопировать параметр
  • используемый для входа [только 111]

ссылкой

  • быстрее, так как только указатель передается
  • используемый для входа , и производит
  • , может быть очень опасным, если используется в сочетании с глобальными переменными
4
ответ дан DShook 7 November 2019 в 10:06
поделиться

PHP является также передачей значением.

<?php
class Holder {
    private $value;

    public function __construct($value) {
        $this->value = $value;
    }

    public function getValue() {
        return $this->value;
    }
}

function swap($x, $y) {
    $tmp = $x;
    $x = $y;
    $y = $tmp;
}

$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);

echo $a->getValue() . ", " . $b->getValue() . "\n";

Выводы:

a b

Однако в объектах PHP4 рассматривались как примитивы . Что означает:

<?php
$myData = new Holder('this should be replaced');

function replaceWithGreeting($holder) {
    $myData->setValue('hello');
}

replaceWithGreeting($myData);
echo $myData->getValue(); // Prints out "this should be replaced"
2
ответ дан grom 7 November 2019 в 10:06
поделиться

Что касается J , хотя есть только, AFAIK, передача по значению, существует форма передачи по ссылке, которая позволяет перемещать большое количество данных. Вы просто передаете глаголу (или функцию) нечто, известное как локаль. Это может быть экземпляр класса или просто общий контейнер.

spaceused=: [: 7!:5 <
exectime =: 6!:2
big_chunk_of_data =. i. 1000 1000 100
passbyvalue =: 3 : 0
    $ y
    ''
)
locale =. cocreate''
big_chunk_of_data__locale =. big_chunk_of_data
passbyreference =: 3 : 0
    l =. y
    $ big_chunk_of_data__l
    ''
)
exectime 'passbyvalue big_chunk_of_data'
   0.00205586720663967
exectime 'passbyreference locale'
   8.57957102144893e_6

Очевидный недостаток заключается в том, что вам нужно каким-то образом знать имя вашей переменной в вызываемой функции. Но этот метод может безболезненно перемещать большой объем данных. Вот почему, хотя технически это не передается по ссылке, я называю это «почти так».

3
ответ дан 7 November 2019 в 10:06
поделиться
Другие вопросы по тегам:

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