Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

Почему изменяются поля в глобальной переменной   Найти похожие ветки 

 
Михаил   (2012-02-26 20:19) [0]

Есть небольшая программка:

program Project1;

{$APPTYPE CONSOLE}

uses
 SysUtils;

// Некая структура исходных данных
type
 TinData = record
   id : Integer;
   a  : array of Integer;
end;

// Процедура с параметром ссылкой
procedure Proc1(inData: TinData); forward;

var
 inData: TinData;

procedure Proc1(inData: TinData);
begin
 inData.id := 30;
 inData.a[0] := 1;
 inData.a[1] := 2;
end;

begin
// Задаем начальные параметры структуры исходных данных
 inData.id := 25;
 SetLength(inData.a, 2);
 inData.a[0] := 110;
 inData.a[1] := 115;

// Передаем копию переменной inData в процедуру
// и изменяем значения ее полей
 Proc1(inData);

// Выводим результат
 writeln("id = ", inData.id);
 writeln("a[0] = ", inData.a[0]);
 writeln("a[1] = ", inData.a[1]);
 readln;
end.


На выходе получаю такой результат:

id = 25
a[0] = 1
a[1] = 2


Вопрос: Почему значение поля id не изменилось, а значения массива изменились в глобальной переменной inData.

По идее если я передаю параметр по ссылке, программа должна сделать копию переменной и не влиять на значение глобальной.
Или я не прав?
Заранее благодарен!!!


 
Сергей М. ©   (2012-02-26 20:33) [1]

поле inData.a есть копия указателя на управл.структуру одного и того же дин.массива, а не копия этого массива


 
Amoeba_   (2012-02-26 20:56) [2]


> Сергей М. ©   (26.02.12 20:33) [1]
>
> поле inData.a есть копия указателя на управл.структуру одного
> и того же дин.массива, а не копия этого массива

что как раз очень хорошо видно под отладчиком


 
Dimka Maslov ©   (2012-02-26 21:17) [3]


> По идее если я передаю параметр по ссылке


Передача параметра по ссылке подразумевает использование ключевого слова var перед именем параметра в описании аргументов функции.


 
oxffff ©   (2012-02-26 21:36) [4]


> По идее если я передаю параметр по ссылке, программа должна
> сделать копию переменной и не влиять на значение глобальной.
>
> Или я не прав?
> Заранее благодарен!!!
>


Для динамических массивов в Delphi используется ссылочная семантика копирования,в отличии от семантики по значению.


 
Михаил   (2012-02-27 06:09) [5]

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

Выходит что слово var при передаче параметров касается только статичных переменных. А дин. массивы и указатели всегда передаются по значению (что и приводит к изменению в глобальной переменной).

Блин в Delphi термины по ссылке и по значению такие запутанные((

Благодарю всех за ответы!


 
MBo ©   (2012-02-27 06:33) [6]

Нет, не всё понял...

По ссылке - это с var. По значению - без var.

При передаче по значению считай, что создается копия параметра, и работа происходит с ней. Однако для указательных переменных можно изменить то, на что указывает указатель, и это отразится на внешних данных. Саму же указательную переменную не изменишь.

При передаче по ссылке (с var) можно изменить и саму переменную, в том числе для указательных - изменить адрес.


 
Anatoly Podgoretsky ©   (2012-02-27 08:37) [7]

> Михаил  (27.02.2012 06:09:05)  [5]

дин. массивы и указатели не передаются, передается ссылка


 
icWasya ©   (2012-02-27 14:15) [8]

Var для динмассива означает, что внутри процедуры мы можем изменить его размер.


 
Дмитрий Белькевич   (2012-02-27 17:32) [9]


> По ссылке - это с var. По значению - без var.


По ссылке - с var или с const. Без var/const - массивам при входе в процедуру делается копия, указатели (в том числе на инстансы классов - объекты) передаются как есть.


> Блин в Delphi термины по ссылке и по значению такие запутанные((


Не путай себя. Достаточно знать, что переменные, переданные как var могут быть изменены внутри процедуры и возвращены наружу процедуры измененными. Без var - могут быть изменены, но наружу процедуры эти изменения не видны, так как меняется внутренняя копия данных.

По ссылке или по значению имеет значение для скорости. Понятно, что любое копирование данных уменьшает скорость выполнения, поэтому все массивы (строки в том числе) лучше передавать с модификаторами var или const.


 
Dimka Maslov ©   (2012-02-27 18:42) [10]


> поэтому все массивы (строки в том числе) лучше передавать
> с модификаторами var или const


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



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.47 MB
Время: 0.075 c
15-1330891352
KilkennyCat
2012-03-05 00:02
2013.03.22
Спутниковое телевидение


4-1261315823
GreyWolf
2009-12-20 16:30
2013.03.22
Установка Windows Caption Icons Size локально для приложения


2-1339657502
AntiUser
2012-06-14 11:05
2013.03.22
Как правильно создать наследников фрейма


2-1339945459
ankazh
2012-06-17 19:04
2013.03.22
VISIBLE


2-1342617866
Andrey K
2012-07-18 17:24
2013.03.22
Как в ShortCut вставить цифру с боковой клавиатуры.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский