Вызов конструктора пустого класса на самом деле используют память?

Предположим, что у меня есть класс как

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. Кроме того, я надеюсь, что компилятор оптимизирует другие ответвления далеко в конструкторе. Если кто-либо знает, верно ли это или как проверить, который значительно ценился бы. Я предположил также, что бросок шаблонов в ситуацию не изменяет "пустой класс" проблема сверху, которая является правильной?

9
задан Victor Liu 6 January 2010 в 21:36
поделиться

3 ответа

Цитирую 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";
}

Данная оптимизация безопасна и может быть наиболее полезной. Она позволяет программисту использовать пустые классы для представления очень простых понятий без накладных расходов. Некоторые нынешние компиляторы предоставляют такую "оптимизацию пустого базового класса".

17
ответ дан 4 December 2019 в 10:04
поделиться

Это может, может, не может, в зависимости от обстоятельств. Если вы скажете:

Empty e;
Empty * ep = & e;

то очевидно, что вещи должны быть распределены.

2
ответ дан 4 December 2019 в 10:04
поделиться

Попробуй и увидишь. Многие компиляторы убирают такие временные объекты, когда их просят оптимизировать вывод.

Если разборка слишком сложная, то создайте две функции с разным количеством таких объектов и посмотрите, есть ли разница в расположении стека окружающих их объектов, что-то вроде:

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 в выходной файл. Вы не можете предполагать, что хранилище для объектов окажется в том же порядке, в котором они объявлены в исходном коде.

2
ответ дан 4 December 2019 в 10:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: