1. return x;
если целые значения помещаются в регистер eax, то как быть с структурами?
2. есть ли разница...
myStruc proc()
{
return myStruct(a, b, c);
}
и
myStruc proc()
{
myStruc xxx;
//...
return xxx;
}
(для тех кто не понял: myStruc ето структура)
3. перегруженные операторы
есть две функции:
myStruc add_asm(myStruc &a, myStruc &b);
myStruc add_cpp(myStruc &a, myStruc &b);
возможно ли нечто вроде...
if(isSSE)
operator+ = add_asm;
else
operator+ = add_cpp;
//...
myStruc c = a + b;
operator+ должен конечно быть указателем...
зарание благодарен.
Здравствуйте, ydab, Вы писали:
Y>1. return x;
Y>если целые значения помещаются в регистер eax, то как быть с структурами?
Вызывающая сторона выделяет (на стеке) память под возвращаемый объект и передаёт указатель на неё как неявный параметр.
Функция конструирует объект по этому указателю.
Вызывающая сторона далее распоряжается объектом по своему усмотрению.
Y>2. есть ли разница...
Y>myStruc proc1()
Y>{
Y> return myStruc(a, b, c);
Y>}
Y>и
Y>myStruc proc2()
Y>{
Y> myStruc xxx;
Y> //...
Y> return xxx;
Y>}
Y>(для тех кто не понял: myStruc ето структура)
В самом общем случае — есть:
1) proc1 выполняет конструктор с параметрами, а proc2 — без параметров (и с последующими вызовами методов, чтоб получить такой же результат?)
2) proc1 сразу конструирует возвращаемый объект, а proc2 — конструирует копию объекта xxx.
В ряде случаев компилятор может выполнить оптимизацию (поищи в форуме про RVO — return value optimization) — разместить объект xxx в возвращаемой памяти и сэкономить на копировании.
Но есть ситуации, когда такое невозможно:
myStruc proc()
{
myStruc xxx;
myStruc yyy;
...
if(something()) return xxx; else return yyy; // здесь поневоле придётся копировать из того или другого источника
}
Y>3. перегруженные операторы
Y>есть две функции:
Y>myStruc add_asm(myStruc &a, myStruc &b);
Y>myStruc add_cpp(myStruc &a, myStruc &b);
Y>возможно ли нечто вроде...
Y>if(isSSE)
Y> operator+ = add_asm;
Y>else
Y> operator+ = add_cpp;
Y>//...
Y>myStruc c = a + b;
Y>operator+ должен конечно быть указателем...
Не должен! И быть не может!
Есть 4 варианта:
1) настройка времени компиляции:
inline myStruc operator+ (const myStruc& lhs, const myStruc& rhs)
{
#ifdef SSE
return add_asm(lhs,rhs);
#else
return add_cpp(lhs,rhs);
#endif
}
2) настройка времени линковки
myStruc add(const myStruc& lhs, const myStruc& rhs);
inline myStruc operator+ (const myStruc& lhs, const myStruc& rhs)
{
return add(lhs,rhs); // функция add определена в add_asm.obj и add_cpp.obj
// и линкеру отдаётся либо тот, либо другой вариант
}
3) настройка времени инсталляции
Имеются две одноимённые DLL с разными реализациями функции add
4) наконец, настройка времени выполнения
// add.h
extern myStruc (*add)(const myStruc& lhs, const myStruc& rhs);
inline myStruc operator+ (const myStruc& lhs, const myStruc& rhs)
{
return add(lhs,rhs);
}
// add.cpp
myStruc (*add)(const myStruc& lhs, const myStruc& rhs) = using_sse() ? add_asm : add_cpp;
Здравствуйте, Кодт, Вы писали:
К>Вызывающая сторона выделяет (на стеке) память под возвращаемый объект и передаёт указатель на неё как неявный параметр.
А если обьект уже существует(на стеке)?
void proca()
{
myStruc ms;
ms = procb();
}
значит procb(); ето procb(myStruc* param); ?
Здравствуйте, ydab, Вы писали:
Y>Здравствуйте, Кодт, Вы писали:
К>>Вызывающая сторона выделяет (на стеке) память под возвращаемый объект и передаёт указатель на неё как неявный параметр.
Y>А если обьект уже существует(на стеке)?
Y>Y>void proca()
Y>{
Y> myStruc ms;
Y> ms = procb();
Y>}
Y>
Y>значит procb(); ето procb(myStruc* param); ?
Есть две разновидности RVO — экономия на копировании в return local_var и экономия на копировании T var = f()
В твоём примере объект ms уже создан, поэтому будет выполнено присваивание.
Впрочем, компилятор может "догадаться", что если myStruc это POD, то инициализация и присваивание сработают одинаково.
А вот здесь
void proca()
{
myStruc ms1 = procb(); // допускается RVO
myStruc ms2 (procb()); // явно указано, что используется конструктор копирования
}