воскресенье, 20 июня 2010 г.

Кое-что новое


Продолжая тему секретных приемов в C++, знаете, чем отличаются два выражения внизу?

X *x = new X;
X *y = new X();

Если класс X не содержит конструктора по умолчанию, определенного пользователем, для y все члены-данные примитивных типов будут инициализированы нулями, в то время как в x будет мусор.

Проверочный пример



#include <iostream>

class X
{
public:
void print()
{
std::cout << "not_init = " << m_not_init << ", init = " << m_init << std::endl;
}

protected:
int m_not_init;
int m_init;
};

class Y
{
public:
Y()
: m_init(1)
{
}

void print()
{
std::cout << "not_init = " << m_not_init << ", init = " << m_init << std::endl;
}

int notInit() const
{
return m_not_init;
}

int init() const
{
return m_init;
}

private:
int m_not_init;
int m_init;
};

class Z: public Y
{
public:
void print()
{
std::cout << "Y::not_init = " << notInit() << ", Y::init = " << init() << ", own = " << m_own << std::endl;
}

private:
int m_own;
};

int main()
{
{
X *x1 = new X, *x2 = new X();
x1->print(); x2->print();
}
std::cout << std::endl;
{
Y *y1 = new Y, *y2 = new Y();
y1->print(); y2->print();
}
std::cout << std::endl;
{
Z *z1 = new Z, *z2 = new Z();
z1->print(); z2->print();
}
return 0;
}


выдает следующее:


not_init = -1819044973, init = -1819044973
not_init = 0, init = 0

not_init = -1819044973, init = 1
not_init = -1819044973, init = 1

Y::not_init = -1819044973, Y::init = 1, own = -1819044973
Y::not_init = -1819044973, Y::init = 1, own = -1819044973

4 комментария:

  1. а разве и в том и в другом случае не вызовется конструктор без аргументов?

    ОтветитьУдалить
  2. @alex: проапдейтил текст, спасибо за вопрос.

    ОтветитьУдалить
  3. $ g++ fml.cpp
    fml.cpp: In member function ‘void Z::print()’:
    fml.cpp:34: error: ‘int Y::m_not_init’ is private
    fml.cpp:44: error: within this context
    fml.cpp:35: error: ‘int Y::m_init’ is private
    fml.cpp:44: error: within this context

    после замены private на protected:


    not init = 0, init = 0
    not init = 0, init = 0

    not init = 0, init = 1
    not init = 0, init = 1

    not init = 0, init = 1
    not init = 0, init = 1

    Конечно, еще надо повтыкать в код и в стандарт, но по-моему, не все так просто.

    ОтветитьУдалить
  4. @Alex: упс, конечно же я в пост вставил не тот пример :) фиксед.

    я смотрел в online comeau; а gcc в дебаге у меня обнуляет дополнительно Z::own в обоих случаях и Z::not_init в последнем примере.

    ОтветитьУдалить