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

Вниз

const и динамические массивы (строки)   Найти похожие ветки 

 
Leoley ©   (2016-01-13 17:18) [0]

Вот забавная штука, не противоречит ли друг другу объявление:

procedure My(..., const s: string, ...);

директива const и реализация динамических массивов и строк в Delphi?
Я к тому, что абсолютно валидный код:

procedure My(..., const s: string, ...);
var
 localS: string;
begin
 localS := s;
...

уже меняет структуру данных, на которую ссылается переменная s. А это как бы противоречит директиве const, которая должна обеспечить неприкосновенность s, а в реальности обеспечивает лишь частичную неприкосновенность?


 
кгшзх ©   (2016-01-13 17:22) [1]

конст в этом месте никак с неприкосновенностью не связана.


 
Leoley ©   (2016-01-13 17:26) [2]

Думаешь?

а чем тогда отличается var от out?


 
кгшзх ©   (2016-01-13 17:26) [3]

ты не первый кто путает смысл const при объявлении константы
и const перед формальным параметром.

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

конст у параметра никаким образом ничего такого не гарантирует про неприкосновенность фактического параметра. вообще.
он совсем про другое.


 
Leoley ©   (2016-01-13 18:06) [4]

>он совсем про другое.

про что?


 
Rouse_ ©   (2016-01-13 18:36) [5]


> не противоречит ли друг другу объявление:

Не противоречит


 
кгшзх ©   (2016-01-13 19:25) [6]

про что?

хотя это и тайна, но я тебе скажу секретный код доступа.
нажимаешь в delphi f1 и открываются секретные материалы сионских мудрецов.
там все и написано про конст у формальных параметров


 
Leoley ©   (2016-01-13 19:54) [7]

Так и написано:

Constant Parameters
A constant (const) parameter is like a local constant or read-only variable


То есть, переменная только для чтения. И тем не менее с вышеуказанным кодом счетчик ссылок МЕНЯЕТСЯ, то есть происходит запись.


 
Rouse_ ©   (2016-01-13 20:01) [8]


> Leoley ©   (13.01.16 19:54) [7]

Нет read-only переменных, есть только конструкции языка, которые не дают тебе выстрелить в ногу :)


 
Игорь Шевченко ©   (2016-01-13 21:09) [9]

http://stackoverflow.com/questions/1600991/are-there-any-advantages-in-using-const-parameters-with-an-ordinal-type
http://stackoverflow.com/questions/11001477/what-difference-does-it-make-when-i-use-const-in-a-procedures-parameter


 
кгшзх ©   (2016-01-13 21:42) [10]

счетчик ссылок МЕНЯЕТСЯ

Даже если он и меняется, то только на время жизни твоей локальной localS, которая живет в стеке и умрет при выходе из My.
Это если еще не цепляться к тому, что счетчик ссылок это одно, а неизменяемость значений - другое (хотя можно и прицепиться)


 
Leoley ©   (2016-01-13 22:08) [11]

Попробую привести другой пример.

Имеем EXE и DLL, которая экспортирует такую процедуру:

1)
procedure Test(const s: string);
begin
 ShowMessage(s);
end;


Я могу вызывать из EXE такую процедуру без всяких ShareMem, все будет абсолютно корректно.
При этом я не могу написать так:

2)
procedure Test(const s: string);
begin
 s[1] := "A";
 ShowMessage(s);
end;


Это не скомпилируется. Переменная "s" как бы защищена от модификации.

Теперь возьмет другой код:

3)
var G_TEXT: string;
...
procedure Test(const s: string);
begin
 G_TEXT := s;
 ShowMessage(s);
end;


Код валидный. И он должен обеспечить "защиту" переменной s от модификации, как в примерах 1) и 2).
Но при этом после возврата управления из DLL в случае 3) менеджер памяти не очистит память, занимаемую s. А в случае 1) очистит.

То есть, если я смотрю на "s" как на черный ящик - мне не очень понятно. Я передаю его как const, а тем не менее в третьем случае почему-то происходит нечто, что меняет "s" таким образом, что работа моего кода EXE с "s" изменяется.


 
Leoley ©   (2016-01-13 22:14) [12]


> Даже если он и меняется, то только на время жизни твоей
> локальной localS, которая живет в стеке и умрет при выходе
> из My.

слушай, ну ты же понимаешь, что это тестовый пример. В тестовом примере да, происходит ДВОЙНОЕ изменение переменной, в результате которого все возвращается в исходный вид. В посте [11] я привел другой пример, где переменная "s" меняется на неопределенное время.

Конечно, это философский вопрос - является ли счетчик ссылок частью переменной "s". Но ведь счетчик есть, он спроектирован именно как часть типа string, он в явном виде определяется через переменную s (по отрицательному смещению по моему), так что... в связи со всеми этими размышлениями и возникла ветка :)


 
кгшзх ©   (2016-01-13 22:24) [13]

счетчик ссылок строк - это не твоя головная боль в том случае если ты таки пользуешься типом string.
При этом как бы ты не извращался, ничто никуда не утечет, и раньше времени никуда не испарится.
Как в тестовых так и в других примерах.


 
кгшзх ©   (2016-01-13 22:27) [14]

Я передаю его как const, а тем не менее в третьем случае почему-то происходит нечто, что меняет "s"

включаем на минуту твою логику:

function x(const a : string)  //ну это понятно, это чтобы не менялось
function x(var a : string)    // снова понятно. это чтобы менялось
function x(a : string)         //wtf?!!!! а это-то тогда что за хрень? зачем это вообще?


 
кгшзх ©   (2016-01-13 22:32) [15]

Код валидный. И он должен обеспечить "защиту" переменной s от модификации, как в примерах 1) и 2).

нет нет и нет.
никакой защиты он не должен обеспечивать.

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

И писатели компилятора при этом никакой "защиты" от тебя самого и не имели ввиду.


 
кгшзх ©   (2016-01-13 22:52) [16]

вот есть конфеты "птичье молоко". ну или были такие конфеты.
так вот. те кто придумал их, не имели ввиду ни птиц, ни молока, ни тем более молока птичьего.
они как бы хотели сказать, что если чел попробовал вообще все, что существует, и познал все вкусы (вообще все), то вот тебе конфеты как бы со вкусом того, чего вообще не существует.

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

а о защите от записи или изменения или еще чего-то подобного он вообще при этом не думал.

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

но в "птичьем молоке" нет птичьего молока.


 
Германн ©   (2016-01-14 02:05) [17]


> кгшзх ©   (13.01.16 22:52) [16]
>
> так и борланд, когда придумал конст для параметров, он имел
> ввиду оптимизацию передачи параметра в функцию.
>
> а о защите от записи или изменения или еще чего-то подобного
> он вообще при этом не думал.

А о чём "он тогда думал"? И что "имел ввиду"?
Я до сих пор думал и думаю, что классификатор const был придуман для того чтобы можно было передать параметр по ссылке вместо передачи по значению (т.е. без копирования). Но с запрещением изменения оригинального значения.


 
кгшзх ©   (2016-01-14 07:01) [18]

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

с передачей по ссылке конст связан еще меньше чем с защитой от модификации.


 
sniknik ©   (2016-01-14 10:02) [19]

> Теперь возьмет другой код:

> 3)
> var G_TEXT: string;
> ...
> procedure Test(const s: string);
> begin
>  G_TEXT := s;
>  ShowMessage(s);
> end;


что то мне подсказывает... без проверки чисто "интуиция", что если код будет типа -
var G_TEXT: string;
...
procedure Test(const s: string);
begin
 G_TEXT := s;
 G_TEXT[1] := "!";
 ShowMessage(G_TEXT);
end;


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


 
virex(home) ©   (2016-01-14 11:28) [20]

>Leoley ©   (13.01.16 17:18) [0]

не понятно чего тут непонятного?

локальной !переменной присваивается значение !константы. константа не изменяется


 
Германн ©   (2016-01-15 01:52) [21]


> кгшзх ©   (14.01.16 07:01) [18]
> с передачей по ссылке конст связан еще меньше чем с защитой
> от модификации.

Поясни.


 
кгшзх ©   (2016-01-15 08:35) [22]

"ипполит, ну какой же вы тупой"

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

Если использовать конст перед параметром, то иногда параметр уйдет по ссылке, а иногда уйдет по значению.

А если НЕ использовать конст, то параметр снова иногда уйдет по ссылке, а иногда по значению.


 
кгшзх ©   (2016-01-15 08:55) [23]

про конст у параметров на пальцах.

сидит банкир и гоняет в любимые танчики.
приходите вы и просите у него кредит в мульон дойларов.
банкир груснеет, так как понимает, что надо собирать кредитный комитет, посылать инкассаторов за наличкой, создавать резервы, учитывать обеспечение.....
в общем банкиру ясно, что танчики на сегодня накрылись.
но вы говорите ему, что кредит нужен сроком на 20 секунд, пользоваться бабками вы не планируете, а вам всего лишь нужно сделать селфи с чемоданом денег.
банкир при этом сразу облегченно вздыхает, достает из тумбочки свой личный миллион зеленых, дает его вам на 20 секунд, после чего продолжает рубиться в wot.

в сценке участвовали:
банкир = компилятор
заемщик = прикладной программист
мильон денег = строка
информация о том что кредит нужен только для селфи = слово const

когда заемщик сказал, что кредит нужен для селфи (нарисовал const перед параметром)
банкир понял, что можно не заморачиваться по всем правилам, а дать заемщику левый чемодан денег (возможно вообще не настоящих)

при этом:
программер получил все что хотел в полном объеме.
банкир выдавая по упрощенной схеме "какбыкредит" думал только о своих танчиках.
ни о каких мерах по защите заемщика в случае если он обманет и убежит с чемоданом фальшивых долларов в магазин покупать мошыно - банкир не думал.

ну а компилер увидев "конст", тоже ни о чем таком не думает, а просто генерит "облегченный" машинный код.


 
Sha ©   (2016-01-15 10:14) [24]

> кгшзх ©   (15.01.16 08:55) [23]

Прикольная аналогия, и ее можно продолжить)

Потом тот же клиент просит у банкира ключ от сейфа. Понятное дело, на 20 секунд, чтоб сделать селфи.
Банкир соглашается, а на следующий день обнаруживает, что в сейфе пусто.
Копия ключа работает также здорово, как настоящий ключ.


 
кгшзх ©   (2016-01-15 10:25) [25]

так суть не в том, что там может все поломаться.

суть в том, что const в параметрах  - это не просьба от разраба к компилятору "защити мои параметры и переменные"

const в параметрах - это торжественное обещание разработчика, в котором он САМ говорит компилеру, что не собирается менять значение параметра внутри функции.
И дается оно с целью тово, чтобы компилер мог "играть в танчики" не заморачиваясь с полноценной передачей параметра.

вся суть только в этом и ни в чем еще.


 
Sha ©   (2016-01-15 11:37) [26]

> кгшзх ©   (15.01.16 10:25) [25]

Так и я о том же, [24] адресовано не тебе, а автору ветки.

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


 
DayGaykin ©   (2016-01-15 14:17) [27]

Так const x:string - в параметре гарантирует, что не изменится указатель, а не сама строка на который этот указатель указывает.
И за этим компилятор будет следить:
function (const s: string);
begin
 s := ""; // такое не соберется.
end;


А то что находится по указателю менять можно.
Никого же не смутит изменение объекта в таком коде:
function (const f: TForm);
begin
 f.Caption := "Hello";
end;


 
Германн ©   (2016-01-16 01:34) [28]


> кгшзх ©   (15.01.16 08:35) [22]
>
> "ипполит, ну какой же вы тупой"
>
> конст не связан с передачей по ссылке потому, что ты не
> можешь управлять способом передачи по ссылке используя конст.
>
>
> Если использовать конст перед параметром, то иногда параметр
> уйдет по ссылке, а иногда уйдет по значению.

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


 
Sha ©   (2016-01-16 16:05) [29]

> Германн ©   (16.01.16 01:34) [28]
> хочу знать когда параметр передаётся по ссылке

Почему бы просто не передавать адрес переменной в таком случае?
Иногда подходит использование var-параметров.
Особенно, если приходится часто менять типы переменных, например: record <=> class. Правда, при этом возможна лишняя операция загрузки адреса, но это почти микроскопическое зло.


 
Ingener ©   (2016-01-16 20:38) [30]

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

ты хотел сказать, что так должно быть в теории.

Но в посте [11], в примере 3) приведена ситуация с Exe и Dll.
несмотря на передачу по const переменную так изменили, что она не будет финализирована после возвращения управления в exe. Причем изменили неявно, в виду особенностей работы string.
И это именно головная боль, потому что без sharemem в проекте будет утечка памяти. Если же код dll будет изменен на такой:

var G_TEXT: string;
...
procedure Test(const s: string);
begin
 G_TEXT := s;
 UniqueString (G_TEXT);
 ShowMessage(s);
end;


то утечки не будет и без ShareMem.

>нет нет и нет.
никакой защиты он не должен
>обеспечивать.
...
>И писатели компилятора при
> этом никакой "защиты" от тебя
>самого и не имели ввиду.

Если ты прав, то почему защита таки обеспечивается?

procedure Test(const s: string);
begin
s := "Abcd";
end;


и такой код:

procedure Test(const s: string);
begin
s[1] := "A";
end;


Вызовут критическую ошибку при компиляции.Не предупреждение выдается, а ошибка.

При этом в справке написано:

A constant (const) parameter is like a local constant or read-only variable

Если ты прав - то почему авторы продукта сравнивают передачу по const с локальными константами и переменными только для чтения?


 
Ingener ©   (2016-01-16 20:43) [31]

>Так const x:string - в параметре
>гарантирует, что не изменится
>указатель, а не сама строка
>на который этот указатель
> указывает.

если это так, то почему такой код:

procedure Test(const s: string);
begin
s[1] := "A";
end;


вызывает ошибку компиляции?
указатель не меняется, меняется строка на которую указывает указатель


 
DayGaykin ©   (2016-01-16 21:05) [32]


> Ingener ©   (16.01.16 20:43) [31]
>

Я думаю это защита от дурака.


 
кгшзх ©   (2016-01-16 21:17) [33]

Если ты прав, то почему защита таки обеспечивается?

рассматривай это как побочный эффект.
никакой защиты они не имели ввиду.
они имели ввиду только оптимизацию передачи строки.
но в результате такой оптимизированной передачи ты таки не можешь делать того, чего САМ обещал не делать.

И для особо упертых снова повторяю.
Вводя конст для параметров, борланд В ПЕРВУЮ ГОЛОВУ
думал об
ОПТИМИЗАЦИИ СПОСОБА ПЕРЕДАЧИ ПАРАМЕТРА

а то, что в результате такой передачи с параметром уже НЕЛЬЗЯ делать того, чего ВЫ САМИ ОБЕЩАЛИ НЕ ДЕЛАТЬ с параметром  - бесплатный бонус компилятора.


 
Ingener ©   (2016-01-16 21:24) [34]

>Я думаю это защита от дурака.

ну как бы да. Программист объявляет константы, чтобы дать понять компилятору, что он не намерен менять их значения. и компилятор следит, чтобы было так.

И аргумент const также объявляет что эта переменная не будет меняться внутри подпрограммы, после чего компилятор также следит, чтобы ты не ошибся. все логично, так везде и продумано.

И статическая типизация туда же. Ты объявляешь о намерениях и компилятор следит, чтобы ты не ошибся и не сделал ошибку, пытаясь провести действия не поддерживаемые этим типом.

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


 
Kerk ©   (2016-01-16 21:25) [35]


> указатель не меняется

Меняется. Copy On Write потому что.

Легко же проверить:
procedure test(s: string);
begin
 s[1] := "X";
 ShowMessage("s="+s);
end;

procedure TForm9.FormCreate(Sender: TObject);
var
 t: string;
begin
 t := "123";
 test(t);
 ShowMessage("t="+t);
end;


Почитай что-нибудь о работе строк.


 
кгшзх ©   (2016-01-16 21:27) [36]

Я думаю это защита от дурака.

Мудрая мысль воистену.
Если "конст" придуман авторами компилера как защита от дурака,
а слово конст должен вставить в программу сам потенциальный дурак,
то получается, что писатели компилятора были еще тупее
чем авторы версии о том, что конст - это была придумка от дурака.


 
Ingener ©   (2016-01-16 21:31) [37]

Удалено модератором


 
кгшзх ©   (2016-01-16 21:43) [38]

а откуда такая уверенность?

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

так какой смысл авторам компилера париться на тему что ты там будешь делать с ее локальной копией внутри функции?
можешь сказать?
не можешь.
так как никакого смысла париться и печалиться об этом нет.

но есть смысл снизить накладные расходы на передачу строкового параметра.

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

и получаешь ты его ЭКОНОМНЫМ образом.

а то что его ЕЩЕ и реально менять при этом становится нельзя - так ты и сам тово хотел.


 
Ingener ©   (2016-01-16 21:48) [39]

Удалено модератором


 
кгшзх ©   (2016-01-16 22:04) [40]

Удалено модератором



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

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

Наверх





Память: 0.57 MB
Время: 0.043 c
15-1450281394
aka
2015-12-16 18:56
2017.01.15
Чтение/запись графа из файла


15-1448832602
Юрий
2015-11-30 00:30
2017.01.15
С днем рождения ! 30 ноября 2015 понедельник


15-1448185459
Limpo
2015-11-22 12:44
2017.01.15
Oracle хранимые процедуры


2-1422093481
Некто
2015-01-24 12:58
2017.01.15
Почему выводится неправильное число (указатели)?


1-1340607264
viosvi
2012-06-25 10:54
2017.01.15
ориентация листа OpenOffice





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский