|
Результаты опроса: f(const x) ?
|
постоянно - всё, что передаю по значению, должно быть незименным
|
|
0 |
0% |
зависит от ситуации (детали - в посте)
|
|
0 |
0% |
никогда - не вижу смысла функции запрещать играться с копиями на стеке
|
|
6 |
100.00% |
27.06.2012, 01:46
|
#1
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
f(const x)
Часто ли вы дополнительно "защищаете" аргументы функции, делая им каст в const, например:
void Save2File(const char* const FileName);
Гарантируя тем самым, что внутри функции значение переменной изменено не будет (в примере - и адрес, и размещённые по нему данные, но интересует только "защита" адреса).
Отдельно оговорюсь: "защита" именно копируемых данных (передаваемых по значению, а не по ссылке или через указатель), т.е. от изменения которых в вызывающем коде ничего не меняется.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
27.06.2012, 02:07
|
#2
|
☭
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений (для 2,707 пользователей)
|
Ответ: f(const x)
void Save2File(const char* const FileName);
если бы мне платили за килобайты кода - защищал бы
а так это адов бред, имхо.
хотя больше бесит когда по константной ссылке передают всякие инты, чары и флоаты.
|
(Offline)
|
|
Эти 2 пользователя(ей) сказали Спасибо HolyDel за это полезное сообщение:
|
|
27.06.2012, 02:13
|
#3
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Ответ: f(const x)
Сообщение от HolyDel
void Save2File(const char* const FileName);
если бы мне платили за килобайты кода - защищал бы
а так это адов бред, имхо.
хотя больше бесит когда по константной ссылке передают всякие инты, чары и флоаты.
|
Суть: избежать случайного затирания внутри функции.
Ну из серии: скопипастил кусок кода из старой реализации, который оперирует массивом FileName и заодно изменяет адрес, хранимый в указателе (допустим, для той задачи это было адекватно [например, указатель ссылается на последний слеш в переданном имени], а в теперешней - нет) . И бац - ошибка.
Пример синтетический конечно, но, если всё по уму писать, то многое от чего можно отказаться - некоторый контроль (особенно при коллективном программировании) можно возложить на язык.
Не думаю, что часто в реализации вы используете повторно нессылочные аргументы - так чего же их не "закрыть"?
Я не агитирую, я высказываю контраргумент для полноты картины
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
27.06.2012, 02:21
|
#4
|
☭
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений (для 2,707 пользователей)
|
Ответ: f(const x)
локализованная внутри одной функции
если ставим const - то ставим везде. или некрасиво.
в твоем же примере это было бы как то так:
void Save2File1(const char* const FileName)
{
char buff[255];
strcpy(FileName,buff,strlen(FileName)+1);
...код который ставит слеш в buff
и работает с buff
}
который бы успешно скомпилировался и в новой функции. ты же не думаешь, что типы параметров у них будут разные?
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
27.06.2012, 02:35
|
#5
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Ответ: f(const x)
Приблизительно понял смесь из memcpy и strcpy, но я же писал - в новой реализации как раз не нужно что либо делать (на запись) с аргументом.
Для адресования можно просто создать новый указатель (массив, напомню, и так константный).
В то время как в скопированной реализации, бралось имя файла без учёта полного адреса, потому там адекватно использовался "аргументный" указатель:
Отсутствие "защиты" (и копипаст!) приведёт к тому, что выбравшийся из леса конструкций указатель уже будет совсем не тем, что прежде. Он по-прежнему будет ласково отзываться на своё прежнее имя, но тьма уже простёрла руку: внутри него имена всемогущей кучи.
Наличие "защиты" какбэ говорит нам: имя файла определено в рамках функции раз и навсегда. Хотите создавать свои сущности - именуйте их иначе.
Ладно: пусть это будет текущее время, переданное в функцию решения группы диф.ур-ий.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
27.06.2012, 10:26
|
#6
|
☭
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений (для 2,707 пользователей)
|
Ответ: f(const x)
видимо я криво объяснил свою точку зрения. на счет копипаста она довольно проста на самом деле:
1) если у некоторых функций аргумент будет константным а у некоторых нет - то мы выносим детали реализации в интерфейс, а это говно.
2) поэтому, надо или у всех функций делать аргумент константным или у всех не делать
3) если у исходной функциии аргумент константный, то внутри находится код, который эту константность как-то обходит, и этот код будет копипаститься в новую функцию (также с константным аргументом) и успешно будет компилироваться.
4) если же у исходной функции аргумент НЕ константный, а у новой константный - то см пункт 1.
|
(Offline)
|
|
Эти 2 пользователя(ей) сказали Спасибо HolyDel за это полезное сообщение:
|
|
27.06.2012, 10:44
|
#7
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Ответ: f(const x)
Сообщение от HolyDel
видимо я криво объяснил свою точку зрения. на счет копипаста она довольно проста на самом деле:
1) если у некоторых функций аргумент будет константным а у некоторых нет - то мы выносим детали реализации в интерфейс, а это говно.
2) поэтому, надо или у всех функций делать аргумент константным или у всех не делать
3) если у исходной функциии аргумент константный, то внутри находится код, который эту константность как-то обходит, и этот код будет копипаститься в новую функцию (также с константным аргументом) и успешно будет компилироваться.
4) если же у исходной функции аргумент НЕ константный, а у новой константный - то см пункт 1.
|
Более чем доходчиво! Стало понятно после первого прочтения.
Остался лишь риторический осадок: может стоит запрещать изменять аргументы функций, передаваемые по значению правилами языка?
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
27.06.2012, 11:03
|
#8
|
☭
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений (для 2,707 пользователей)
|
Ответ: f(const x)
теоретически должно быть полезно.
на практике я куда чаще сталкивался с удобством изменения параметра (было пару раз), чем с ошибками, связанными из - за его не константности (ни разу не сталкивался).
еще можно делать так (по крайней мере в студии ,не знаю насколько это по стандарту) с одной стороны остается чистый интерфейс - с другой, реализация может учитывать константным оставлять аргумент или нет.
const char* x(const char* value); //Интерфейс
const char* x(const char* const value) //реализацяи
{
value = "begrh"; //ошибка компиляции
return value;
}
|
(Offline)
|
|
27.06.2012, 12:46
|
#9
|
|
Ответ: f(const x)
давайте попробуем заставить llvm ( http://llvm.org/demo/index.cgi ) выдать разный код с const и без, мой пример пока даёт одинаковый код :
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
uintptr_t test1(const int * a)
{
return (uintptr_t)a + 0xff;
}
uintptr_t test2(const int * const a)
{
return (uintptr_t)a + 0xff;
}
int main()
{
int a = 0, b = 0;
printf("%li\n", test1(&a));
printf("%li\n", test2(&b));
}
и выхлоп :
; ModuleID = '/tmp/webcompile/_10893_0.bc'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@.str = private unnamed_addr constant [5 x i8] c"%li\0A\00", align 1
define i64 @test1(i32* %a) nounwind uwtable readnone {
%1 = ptrtoint i32* %a to i64
%2 = add i64 %1, 255
ret i64 %2
}
define i64 @test2(i32* %a) nounwind uwtable readnone {
%1 = ptrtoint i32* %a to i64
%2 = add i64 %1, 255
ret i64 %2
}
define i32 @main() nounwind uwtable {
%a = alloca i32, align 4
%b = alloca i32, align 4
store i32 0, i32* %a, align 4, !tbaa !0
store i32 0, i32* %b, align 4, !tbaa !0
%1 = ptrtoint i32* %a to i64
%2 = add i64 %1, 255
%3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([5 x i8]* @.str, i64 0, i64 0), i64 %2) nounwind
%4 = ptrtoint i32* %b to i64
%5 = add i64 %4, 255
%6 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([5 x i8]* @.str, i64 0, i64 0), i64 %5) nounwind
ret i32 0
}
declare i32 @printf(i8* nocapture, ...) nounwind
кодогенератор в x64 вообще интересно свернул llvm ассемблер :
.file "/tmp/webcompile/_11162_0.bc"
.text
.globl test1
.align 16, 0x90
.type test1,@function
test1: # @test1
.Ltmp0:
.cfi_startproc
# BB#0:
leaq 255(%rdi), %rax
ret
.Ltmp1:
.size test1, .Ltmp1-test1
.Ltmp2:
.cfi_endproc
.Leh_func_end0:
.globl test2
.align 16, 0x90
.type test2,@function
test2: # @test2
.Ltmp3:
.cfi_startproc
# BB#0:
leaq 255(%rdi), %rax
ret
.Ltmp4:
.size test2, .Ltmp4-test2
.Ltmp5:
.cfi_endproc
.Leh_func_end1:
.globl main
.align 16, 0x90
.type main,@function
main: # @main
.Ltmp7:
.cfi_startproc
# BB#0:
pushq %rax
.Ltmp8:
.cfi_def_cfa_offset 16
movl $0, 4(%rsp)
movl $0, (%rsp)
leaq 259(%rsp), %rsi
movl $.L.str, %edi
xorb %al, %al
callq printf
leaq 255(%rsp), %rsi
movl $.L.str, %edi
xorb %al, %al
callq printf
xorl %eax, %eax
popq %rdx
ret
.Ltmp9:
.size main, .Ltmp9-main
.Ltmp10:
.cfi_endproc
.Leh_func_end2:
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "%li\n"
.size .L.str, 5
.section ".note.GNU-stack","",@progbits
функции в две команды
|
|
|
27.06.2012, 13:14
|
#10
|
☭
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений (для 2,707 пользователей)
|
Ответ: f(const x)
выдать разный код с const и без
|
при чем здесь это?
Импер предлагал использовать const для обнаружения возможных ошибок на этапе компиляции, а не для оптимизации исполнимого кода
|
(Offline)
|
|
27.06.2012, 15:04
|
#11
|
Дэвелопер
Регистрация: 10.09.2007
Сообщений: 1,442
Написано 793 полезных сообщений (для 1,460 пользователей)
|
Ответ: f(const x)
импэ, переходи уже на функциональные языки - там много матана, теорката и главное (!) все переменные - неизменяемые.
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
27.06.2012, 22:21
|
#12
|
[object Object]
Регистрация: 01.08.2008
Адрес: В России
Сообщений: 4,358
Написано 2,472 полезных сообщений (для 6,854 пользователей)
|
Ответ: f(const x)
Сообщение от ffinder
переменные - неизменяемые
|
какие же они тогда "переменные"?
__________________
Retry, Abort, Ignore? █
Intel Core i7-9700 4.70 Ghz; 64Gb; Nvidia RTX 3070
AMD Ryzen 7 3800X 4.3Ghz; 64Gb; Nvidia 1070Ti
AMD Ryzen 7 1700X 3.4Ghz; 8Gb; AMD RX 570
AMD Athlon II 2.6Ghz; 8Gb; Nvidia GTX 750 Ti
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
28.06.2012, 00:18
|
#13
|
Дэвелопер
Регистрация: 10.09.2007
Сообщений: 1,442
Написано 793 полезных сообщений (для 1,460 пользователей)
|
Ответ: f(const x)
Сообщение от Randomize
какие же они тогда "переменные"?
|
еще один пример legacy. они - значения, которые передаются в качестве параметров функций.
но! в математике переменные вовсе не меняют своих значений.
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 12:11.
|