Здравствуйте, night beast, Вы писали:
NB>теоретически Александреску может и прав, но компиляторы должны уметь оптимизировать это дело. NB>и не известно, какой вариант более предпочтителен для оптимизации.
Передача по значению всё-таки предпочтительнее.
Пример:
В случае foo компилятор может установить, что на n (как и на i) нет никакого влияния извне, и сделать цикл от 0 до n так, как удобнее (например, с обратным отсчётом)
В случае bar таких гарантий нет (возможна ситуация, как xxx + main под чертой), и поэтому нужно перечитывать n на каждой итерации.
[]
К>В случае foo компилятор может установить, что на n (как и на i) нет никакого влияния извне, и сделать цикл от 0 до n так, как удобнее (например, с обратным отсчётом) К>В случае bar таких гарантий нет (возможна ситуация, как xxx + main под чертой), и поэтому нужно перечитывать n на каждой итерации.
Это может произойти только в многопоточном окружении. Разве компилятор должен рассматривать такой случай?
Здравствуйте, Кодт, Вы писали:
NB>>теоретически Александреску может и прав, но компиляторы должны уметь оптимизировать это дело. NB>>и не известно, какой вариант более предпочтителен для оптимизации.
К>Передача по значению всё-таки предпочтительнее. К>Пример: К>В случае foo компилятор может установить, что на n (как и на i) нет никакого влияния извне, и сделать цикл от 0 до n так, как удобнее (например, с обратным отсчётом) К>В случае bar таких гарантий нет (возможна ситуация, как xxx + main под чертой), и поэтому нужно перечитывать n на каждой итерации.
Пример не совсем корректен, поскольку функции делают разные вещи, однако идею уловил. Спасибо.
В реальной ситуации по прежнему больше доверяю тестам
Здравствуйте, Erlond, Вы писали:
E>Есть 3 способа передавать аргументы в функцию:
E>1). по значению; E>2). по ссылке; E>3). по указателю.
E>В 1-м случае создаётся временный объект, в который копируется значение аргумента, и функция работает с временным объектом. Внутри функции значения переданных аргументов можно изменять, это изменение никак не отразится за пределами функции. Недостаток — непроизводительные потери на создание временного объекта и копирование данных, что может быть достаточно накладно при больших объёмах.
E>Во 2-м случае функция получает адрес объекта и работает с ним напрямую, поэтому изменение значения аргумента, переданного функции по ссылке, будут видны за пределами функции. Это можно устранить, объявив ссылку константной. Достоинство — не происходит создания временного объекта и копирования даннных.
E>В 3-м случае почти то же самое, что и во 2-м, передаётся только указатель на данные, создания временного объекта не происходит. Отличия — указатель может быть NULL, при обращении к данным требуется операция разыменования (косвенная адресация).
Врменный объект создаётся всегда. Просто во втором и третем случаях временный объект — указатель. Соответственно, если размер объекта не больше размера указателя, то время на передачу одинаковое.
Во втором и третьем случае разыменование происходит одинакого.
Здравствуйте, night beast, Вы писали:
NB>Здравствуйте, np9mi7, Вы писали:
КЛ>>>а что собенного в том, что интегральные типы передаются по ссылке?
N>>Тратиться дополнительное время на один уровень косвенности, а памяти отъедает меньше чем фактический тип только в случае long long;
NB>какие нибудь цифры, поддверждающие предположение имеются?
#include <iostream>
using namespace std;
int foo(int n){
if (n > 1)
return n * foo(n - 1);
else
return 1;
}
int boo(const int& n){
if (n > 1)
return n * boo(n - 1);
else
return 1;
}
int main(int argc, char** argv){
cout << "sizeof(int): " << sizeof(int) << endl;
cout << "sizeof(const int&): " << sizeof(const int&) << endl;
if (argc == 2){
if (argv[1][0] == '1'){
cout << "by value" << endl;
for (int i = 0; i < 10000000; i++)
foo(30);
}
if (argv[1][0] == '2'){
cout << "by const &" << endl;
for (int i = 0; i < 10000000; i++)
boo(30);
}
}
}
moriarty@earthquake:~$ time ./a.out 1
sizeof(int): 4
sizeof(const int&): 4
by value
real 0m2.705s
user 0m2.704s
sys 0m0.004s
moriarty@earthquake:~$ time ./a.out 2
sizeof(int): 4
sizeof(const int&): 4
by const &
real 0m3.056s
user 0m3.048s
sys 0m0.008s
moriarty@earthquake:~$ gcc --version
gcc (GCC) 4.0.3 (Ubuntu 4.0.3-1ubuntu5)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Здравствуйте, Константин Л., Вы писали:
КЛ>Это может произойти только в многопоточном окружении.
Неправда. Мой пример однопоточный, и в нём всё происходит.
КЛ> Разве компилятор должен рассматривать такой случай?
Компилятор не имеет права оптимизировать работу с переменными, которые могут быть доступны под другим именем.
Вот ещё один пример
int x = 0;
int *p = &x;
int i, n; // в этом месте переменные i и n строго локальныfor(i=0, n=10; i!=n; ++i) // и поэтому их можно разместить в регистрах
--*p; // а то и вообще развернуть циклif(rand()%2)
p = &n;
// начиная с этого места n может меняться извнеfor(i=0, n=10; i!=n; ++i)
--*p;
R>Врменный объект создаётся всегда. Просто во втором и третем случаях временный объект — указатель. Соответственно, если размер объекта не больше размера указателя, то время на передачу одинаковое.
Время работы конструктора намного больше, чем время пересылки байтов. Поэтому double лучше передавать по значению, а CString — по ссылке, несмотря на то, что ее размер равен размеру указателя.
R>Во втором и третьем случае разыменование происходит одинакого.
Здравствуйте, HiSH, Вы писали:
КЛ>>>>а что собенного в том, что интегральные типы передаются по ссылке?
N>>>Тратиться дополнительное время на один уровень косвенности, а памяти отъедает меньше чем фактический тип только в случае long long;
NB>>какие нибудь цифры, поддверждающие предположение имеются?
HSH>moriarty@earthquake:~$ time ./a.out 2
HSH>real 0m3.056s
HSH>user 0m3.048s
HSH>sys 0m0.008s
HSH>"И все-таки, она вертится"
угу
собственно, мой поинт был в том, что не стоит безоговорочно верить всему что говорят.
например, передача плейсхолдера по ссылке может быть более быстрой чем передача по значению.
по ситуации смотреть надо.