c++, calling conventions и возвращаемые значения
От: ydab  
Дата: 28.05.05 12:56
Оценка:
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+ должен конечно быть указателем...

зарание благодарен.
Re: c++, calling conventions и возвращаемые значения
От: Кодт Россия  
Дата: 28.05.05 17:44
Оценка: 5 (1)
Здравствуйте, 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;
Перекуём баги на фичи!
Re[2]: c++, calling conventions и возвращаемые значения
От: ydab  
Дата: 28.05.05 20:04
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Вызывающая сторона выделяет (на стеке) память под возвращаемый объект и передаёт указатель на неё как неявный параметр.

А если обьект уже существует(на стеке)?

void proca()
{
  myStruc ms;
  ms = procb();
}


значит procb(); ето procb(myStruc* param); ?
Re[3]: c++, calling conventions и возвращаемые значения
От: Кодт Россия  
Дата: 30.05.05 08:40
Оценка:
Здравствуйте, 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()); // явно указано, что используется конструктор копирования
}
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.