Предположим, что у меня есть класс как
class Empty{
Empty(int a){ cout << a; }
}
И затем я вызываю его использование
int main(){
Empty(2);
return 0;
}
Это заставит память быть выделенной на стеке для создания "Пустого" объекта? Очевидно, аргументы должны быть продвинуты на стек, но я не хочу подвергаться любым дополнительным издержкам. В основном я использую конструктора в качестве статического участника.
Причина, которую я хочу сделать, это из-за шаблонов. Фактический код похож
template <int which>
class FuncName{
template <class T>
FuncName(const T &value){
if(which == 1){
// specific behavior
}else if(which == 2){
// other specific behavior
}
}
};
который позволяет мне писать что-то как
int main(){
int a = 1;
FuncName<1>(a);
}
так, чтобы я добрался для специализации одного шаблонного параметра, не имея необходимость определить тип T
. Кроме того, я надеюсь, что компилятор оптимизирует другие ответвления далеко в конструкторе. Если кто-либо знает, верно ли это или как проверить, который значительно ценился бы. Я предположил также, что бросок шаблонов в ситуацию не изменяет "пустой класс" проблема сверху, которая является правильной?
Цитирую Stroustrup:
Почему размер пустого класса не равен нулю? Чтобы адреса двух разных объектов были разными. По той же самой причине, "new" всегда возвращает указатели на разные объекты. Рассмотрим:
class Empty { };
void f()
{
Empty a, b;
if (&a == &b) cout << "impossible: report error to compiler supplier";
Empty* p1 = new Empty;
Empty* p2 = new Empty;
if (p1 == p2) cout << "impossible: report error to compiler supplier";
}
Есть интересное правило, которое гласит, что пустой базовый класс не обязательно должен быть представлен отдельным байтом:
struct X : Empty {
int a;
// ...
};
void f(X* p)
{
void* p1 = p;
void* p2 = &p->a;
if (p1 == p2) cout << "nice: good optimizer";
}
Данная оптимизация безопасна и может быть наиболее полезной. Она позволяет программисту использовать пустые классы для представления очень простых понятий без накладных расходов. Некоторые нынешние компиляторы предоставляют такую "оптимизацию пустого базового класса".
Это может, может, не может, в зависимости от обстоятельств. Если вы скажете:
Empty e;
Empty * ep = & e;
то очевидно, что вещи должны быть распределены.
Попробуй и увидишь. Многие компиляторы убирают такие временные объекты, когда их просят оптимизировать вывод.
Если разборка слишком сложная, то создайте две функции с разным количеством таких объектов и посмотрите, есть ли разница в расположении стека окружающих их объектов, что-то вроде:
void empty1 ( int x )
{
using namespace std;
int a;
Empty e1 ( x );
int b;
cout << endl;
cout << "empty1" << endl;
cout << hex << int ( &x ) << " " << dec << ( &x - &a ) << endl;
cout << hex << int ( &a ) << " " << dec << ( &a - &b ) << endl;
}
, а затем попробуйте запустить эту функцию по сравнению с функцией empty8
, в которой создано восемь Empties. С помощью g++ на x86, если вы возьмете адрес любой из пустот, то получите местоположение между x и a на стеке, следовательно, включите x в выходной файл. Вы не можете предполагать, что хранилище для объектов окажется в том же порядке, в котором они объявлены в исходном коде.