empty base optimization и множественное наследование
От: Аноним  
Дата: 29.08.09 06:50
Оценка: 1 (1)
доброго времени суток!
вот цитата из "Эффективное использование С++" Скотта Мэйерса:

Но имейте в виду, что в общем случае оптимизация EBO применяется только для одиночного наследования. Действующие в С++ правила размещения объектов в памяти обычно делают невозможной такую оптимизацию, если производный класс имеет более одного базового.

Тэг CODE не предназначен для цитирования!!! И делайте предпросмотр.
— Кодт
к сожалению, автор только ссылается на некие правила С++ и не дает никаких комментариев по этому поводу... за сим обращаюсь к Вам — почему в случае impl_0, impl_1, impl_2 и impl_4 компилятор реализовал EBO, а в случае с impl_3 — нет? указывать на то, что в impl_3 empty_base_0 и empty_base_1 следуют друг за другом не нужно. нужно объяснить почему этот факт мешает компилятору реализовать EBO
class empty_base_0
{ };
class empty_base_1
{ };
class storage
{ int                i; };

class impl_0 : public empty_base_0
{ int                g; };
class impl_1 : public empty_base_0, public storage
{ };
class impl_2 : public empty_base_0, public storage
{ int                g; };
class impl_3 : public empty_base_0, public empty_base_1, public storage
{ int                g; };
class impl_4 : public empty_base_0, public storage, public empty_base_1
{ int                g; };

int                _tmain(int argc, _TCHAR* argv[])
{
    int                iSize = 0;
    iSize            = sizeof(impl_0);    // 4
    iSize            = sizeof(impl_1);    // 4
    iSize            = sizeof(impl_2);    // 8
    iSize            = sizeof(impl_3);    // 12
    iSize            = sizeof(impl_4);    // 8
    return 0;
}
empty base optimization ebo
Re: empty base optimization и множественное наследование
От: Николай Ивченков  
Дата: 29.08.09 23:33
Оценка:
Аноним 691:

А>вот цитата из "Эффективное использование С++" Скотта Мэйерса:

А>

Но имейте в виду, что в общем случае оптимизация EBO применяется только для одиночного наследования. Действующие в С++ правила размещения объектов в памяти обычно делают невозможной такую оптимизацию, если производный класс имеет более одного базового.

к сожалению, автор только ссылается на некие правила С++ и не дает никаких комментариев по этому поводу...


Возможно, это какие-то неформальные правила Я как-то пытался найти ответ на схожий вопрос: из какого нормативного текста стандарта следует, что два подобъекта, имеющие один и тот же тип и принадлежащие одному и тому же most derived объекту, должны располагаться по разным адресам. Мои поиски так и не увенчались успехом.

#include <iostream>

struct B
{
    B *ptr() { return this; }
};
struct D : B
{
    B b;
};

int main()
{
    D d;
    std::cout << (d.ptr() == d.b.ptr()) << std::endl; 
}

Может ли равенство d.ptr() == d.b.ptr() быть истинным? Согласно примечанию в 10/5, не может, но примечания не являются нормативными, и разработчики компиляторов вправе их игнорировать. В данном случае VC++ 8.0 и Intel C++ 11.0 располагают data member и базовый подобъект по одному адресу.
Re: empty base optimization и множественное наследование
От: gear nuke  
Дата: 30.08.09 00:01
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>нужно объяснить почему этот факт мешает компилятору реализовать EBO


Боюсь, что объяснения смогут дать только здесь: Visual Studio 2008 Bug Submission Form
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re: empty base optimization и множественное наследование
От: Programador  
Дата: 30.08.09 06:09
Оценка:
Здравствуйте, Аноним, Вы писали:

А>доброго времени суток!


Вроде первый из предков "настоящий". МФЦ "допускает" множественное наследование если первый Object а второй свой. этим impl_3 отличается от impl_4 . Я тут дополнил и запустил
    iSize = sizeof(empty_base_0); // =1
    impl_0 i0;
    empty_base_0 e0;
    e0=i0;
    // i0=e0; ошибка
    empty_base_0 *eb=&i0; 
    *eb=e0; // нет кода

у меня 12 не встречается только 4 и 8, так что 12 похоже от микрософт. ЕМНИП sizeof!=0 Всвязи с этим memcopy( , , sizeof); должен глючить при ЕБО.

А ЕБО что? Законный прием или опция оптимизации?
Re[2]: empty base optimization и множественное наследование
От: Faust Россия  
Дата: 30.08.09 06:49
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>Возможно, это какие-то неформальные правила Я как-то пытался найти ответ на схожий вопрос: из какого нормативного текста стандарта следует, что два подобъекта, имеющие один и тот же тип и принадлежащие одному и тому же most derived объекту, должны располагаться по разным адресам. Мои поиски так и не увенчались успехом.


НИ>
#include <iostream>

НИ>struct B
НИ>{
НИ>    B *ptr() { return this; }
НИ>};
НИ>struct D : B
НИ>{
НИ>    B b;
НИ>};

НИ>int main()
НИ>{
НИ>    D d;
НИ>    std::cout << (d.ptr() == d.b.ptr()) << std::endl; 
НИ>}

НИ>Может ли равенство d.ptr() == d.b.ptr() быть истинным? Согласно примечанию в 10/5, не может, но примечания не являются нормативными, и разработчики компиляторов вправе их игнорировать. В данном случае VC++ 8.0 и Intel C++ 11.0 располагают data member и базовый подобъект по одному адресу.
спасибо за ответ! но мне кажется, в Вашем случае все объяснимо:
struct B
{
    B *ptr() { return this; }
};
struct D : B    // здесь компилятор реализует EBO
{
    B b;    // адрес b совпадает с адресом наследуемого B
};
// sizeof(D) == 1, и Derived.ptr() == Derived.b.ptr()

struct B
{
    B *ptr() { return this; }
};
struct D : B    // здесь компилятор реализует EBO
{
    B b;    // адрес b совпадает с адресом наследуемого B
    char m_c;
};
// sizeof(D) == 2, и Derived.ptr() == Derived.b.ptr()

struct B
{
    B *ptr() { return this; }
};
struct D : B    // здесь компилятор реализует EBO
{
    char m_c;
    B b;    // адрес b не совпадает с адресом наследуемого B
};
// sizeof(D) == 2, и Derived.ptr() != Derived.b.ptr()
вот что у меня получилось в процессе тестирования:
#include <iostream>

struct base_0
{
    base_0*            ptr_0() { return this; }
};
struct derived_0
    : base_0    // здесь компилятор реализует EBO
{
    base_0            m_base;
};
struct base_1
{
    base_1*            ptr_1() { return this; }
};
struct derived_1
    : base_0    // здесь компилятор реализует EBO
    , base_1    // здесь нет! что ему мешает?  :xz: 
{
    char            m_c;
};

int                    _tmain(int argc, _TCHAR* argv[])
{
    derived_0        Derived0;
    std::cout << "sizeof(base_0) = " << sizeof(base_0) << std::endl;
    std::cout << "sizeof(derived_0) = " << sizeof(derived_0) << std::endl;
    std::cout << "&Derived0 = " << &Derived0 << std::endl;
    std::cout << "Derived0.ptr_0() = " << Derived0.ptr_0() << std::endl;
    std::cout << "Derived0.m_base.ptr_0() = " << Derived0.m_base.ptr_0() << std::endl;
    std::cout << "(Derived0.ptr_0() == Derived0.m_base.ptr_0()) == ";
    std::cout << (Derived0.ptr_0() == Derived0.m_base.ptr_0()) << std::endl << std::endl;
    //std::cout << sizeof(base) << sizeof(derived) << (Derived.ptr() == Derived.m_base.ptr()) << std::endl;
    derived_1        Derived1;
    std::cout << "sizeof(base_0) = " << sizeof(base_0) << std::endl;
    std::cout << "sizeof(base_1) = " << sizeof(base_1) << std::endl;
    std::cout << "sizeof(derived_1) = " << sizeof(derived_1) << std::endl;
    std::cout << "&Derived1 = " << &Derived1 << std::endl;
    std::cout << "Derived1.ptr_0() = " << Derived1.ptr_0() << std::endl;
    std::cout << "Derived1.ptr_1() = " << Derived1.ptr_1() << std::endl;
    std::cout << "(Derived1.ptr_0() == Derived1.ptr_1()) == ";
    std::cout << ((void*)Derived1.ptr_0() == (void*)Derived1.ptr_1()) << std::endl;

    return 0;
}

sizeof(base_0) = 1
sizeof(derived_0) = 1
&Derived0 = 0012FF33
Derived0.ptr_0() = 0012FF33
Derived0.m_base.ptr_0() = 0012FF33
(Derived0.ptr_0() == Derived0.m_base.ptr_0()) == 1

sizeof(base_0) = 1
sizeof(base_1) = 1
sizeof(derived_1) = 2
&Derived1 = 0012FF24
Derived1.ptr_0() = 0012FF24
Derived1.ptr_1() = 0012FF25
(Derived1.ptr_0() == Derived1.ptr_1()) == 0
Мой компьютер прогоняет бесконечный цикл за 9 секунд, но, мне кажется, он мог бы сделать это быстрее...
Re[2]: empty base optimization и множественное наследование
От: Faust Россия  
Дата: 30.08.09 07:07
Оценка:
Здравствуйте, Programador, Вы писали:

P>А ЕБО что? Законный прием или опция оптимизации?

вроде как, законный прием...
вот тест на MSVC 8:
    iSize            = sizeof(empty_base_0); // 1
    impl_0            i0;
    empty_base_0    e0;
    e0                = i0;    // нет ошибки и нет кода!!!
    empty_base_0*    eb = &i0; 
    *eb                = e0;    // нет кода
    *eb                = i0;    // нет кода
Мой компьютер прогоняет бесконечный цикл за 9 секунд, но, мне кажется, он мог бы сделать это быстрее...
Re[3]: empty base optimization и множественное наследование
От: Programador  
Дата: 30.08.09 08:02
Оценка:
Здравствуйте, Faust, Вы писали:

F>Здравствуйте, Programador, Вы писали:


P>>А ЕБО что? Законный прием или опция оптимизации?

F>вроде как, законный прием...
F>вот тест на MSVC 8:
F>
F>    empty_base_0    e0;
F>    e0                = i0;    // нет ошибки и нет кода!!!
F>

Пробовал на g++ ему привидение нужно. Причем приведение в краткой форме сейчас небезопасны
     int eee;
     (empty_base_0&)eee=e0; // Ок

только static_cast, раньше указатели неправильные только через void* приводились

А длина разная потому что МС первый взял и сразу до 1 длину расширил. А g++ на ум взял
Re[2]: empty base optimization и множественное наследование
От: Кодт Россия  
Дата: 31.08.09 12:22
Оценка: 2 (1)
Здравствуйте, Николай Ивченков, Вы писали:

НИ>Возможно, это какие-то неформальные правила Я как-то пытался найти ответ на схожий вопрос: из какого нормативного текста стандарта следует, что два подобъекта, имеющие один и тот же тип и принадлежащие одному и тому же most derived объекту, должны располагаться по разным адресам. Мои поиски так и не увенчались успехом.


Из соображений идентичности.
Подобъекты из разных веток наследования не идентичны. А в С++ идентичность определяется адресом. Следовательно... правильно!
А вот к разнотипным объектам отношение идентичности неприменимо, поэтому они могут как угодно накладываться друг на друга, вплоть до совпадения адресов.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[3]: empty base optimization и множественное наследование
От: Николай Ивченков  
Дата: 31.08.09 15:44
Оценка: +1
Кодт:

НИ>>Возможно, это какие-то неформальные правила Я как-то пытался найти ответ на схожий вопрос: из какого нормативного текста стандарта следует, что два подобъекта, имеющие один и тот же тип и принадлежащие одному и тому же most derived объекту, должны располагаться по разным адресам. Мои поиски так и не увенчались успехом.


К>Из соображений идентичности.

К>Подобъекты из разных веток наследования не идентичны. А в С++ идентичность определяется адресом. Следовательно... правильно!

Где в стандарте такое сказано?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.