Вектор, изменяющий размер класса - PullRequest
0 голосов
/ 05 октября 2011

РЕДАКТИРОВАТЬ:
Несмотря на то, что этот вопрос был плохо отформатирован, у него была хорошая уловка. Итак, я редактирую это, чтобы сохранить его в лучшем формате для будущих посетителей, которые наткнулись на этот вопрос.


В приведенном ниже примере кода кто-нибудь может объяснить, почему размер класса отличается от ожидаемого после memcpy?Какова причина?

Здесь - это онлайн-демонстрация Ideone.

#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>

using namespace std;

class A
{
    public:
        int a;
        virtual void f1() { cout <<"inside a::f1\n"; }
        A() { a = 1; }
};

class B
{
    public:
        int b;
        virtual void f2() { cout <<"inside b::f2\n"; }
        virtual void f5() { cout <<"inside b::f5\n"; }
        B() { b = 2; }
};

class C : public A, public B
{
    public:
        int c;
        void f1() { cout <<"inside c::f1\n"; }
        void f2() { cout <<"inside c::f2\n"; }

        virtual void f3() { cout <<"inside c::f3\n"; }
        virtual void f4() { cout <<"inside c::f4\n"; }
        C() { c = 3; }
};


int fun()
{
    int a = 1;
    return a * 2;
}

int main()
{
    C c;
    C c2;
    int (*g)() = &fun;

    void (A::*g1)() = &A::f1;
    void (C::*g2)();

    g2 = &C::f1;
    (c.*g2)();

    printf("%p\n",g2);
    cout << sizeof(g2) << endl;

    g2 = &C::f2;
    (c.*g2)();

    printf("%p\n", g2);

    // Why is the output 1 here in g++ or visual C++?
    cout << g2;
    // Why is the sizeof returning 8? Please explain.
    cout << sizeof(g2) << endl;

    g2 = &C::f1;
    std::vector<unsigned char> a_vec(sizeof(g2));

    memcpy(&a_vec[0], &g2, sizeof(g2));
    for(size_t i = 0; i < sizeof(g2); ++i)     
    {         
        cout << hex << static_cast<unsigned>(a_vec[i]) << " ";
    } 
    cout << endl;

    g2 = &C::f2;
    std::vector<unsigned char> a_vec1(sizeof(g2));
    memcpy(&a_vec1[0], &g2, sizeof(g2));

    for(size_t i = 0; i < sizeof(g2); ++i)     
    {         
        cout << hex << static_cast<unsigned>(a_vec1[i]) << " ";
    } 
    cout << endl;

    cout << sizeof(g) <<endl;
    cout << sizeof(g1) <<endl;
    cout << sizeof(g2) <<endl;

    // Why is sizeof(C) printing 14 and not 20 in visual C++?
    // If yes why is this so ?
    cout << sizeof(C) << endl;
    cout << sizeof(c2) << endl;
    cout << (&c) << endl;
    cout << c.a << endl;
    cout << c.b << endl;
    cout << c.c << endl;

    return 0;
}

Из приведенного выше примера кода вывод, который я получаю:

inside c::f1
0x1
8
inside c::f2
0x5
18
1 0 0 0 0 0 0 0 
5 0 0 0 0 0 0 0 
4
8
8
14
14
0xbffe375c
1
2
3   

Ниже приведены мои вопросы:

  1. Почему вывод 1 здесь в g ++ или визуальном C ++?

    cout << g2; </p>

  2. Почему sizeof возвращает 8?Пожалуйста, объясните.

    cout << sizeof (g2) << endl; </p>

  3. Почему печатается sizeof(C)14 а не 20 в визуальном C ++?Если да, то почему это так?

    cout << sizeof (C) << endl; </p>

Ответы [ 2 ]

3 голосов
/ 05 октября 2011

Почему sizeof возвращает 8. Пожалуйста, объясните?

cout <<sizeof(g2)<<endl;  

возвращает 8, потому что g2 является указателем, а размер указателя в вашей среде равен 8.


Почему вывод 1 здесь в g ++ или визуальном C ++?

cout << g2; 

У << operator нет перегруженной версии, которая принимает указатель. Таким образом, указатель преобразуется в тип bool со значением 1, и cout печатает его.

Стандарт C ++ позволяет это:

C ++ 03 Standard 4.12 Булевы преобразования

1 Значение r арифметики, перечисления, указателя или указателя на тип элемента может быть преобразовано в значение типа bool.


Почему sizeof(C) печатает 14, а не 20 в Visual C ++.

cout<<sizeof(C)<<endl;  

Отображает размер C правильно только в шестнадцатеричном (14 in hex == 20 in decimal). Это связано с тем, что вы использовали манипулятор ввода / вывода hex для печати адреса раньше.

cout<<dec<<sizeof(C)<<endl;

снова переведет манипулятор ввода / вывода в десятичный режим и выдаст 20, как вы ожидаете.


Слово о printf и типе безопасности:

printf не является типобезопасным. При использовании printf пользователь обязан передать ему правильный дескриптор formart и тип данных. В случае несоответствия произойдет неопределенное поведение . Неопределенное поведение означает, что программа может аварийно завершить работу или показать какое-либо странное поведение.

printf ("% p \ n", g2);

Это пример неопределенного поведения, имеется несоответствие в дескрипторе формата и типе данных. Обратите внимание, что компилятор действительно жалуется на это, и вы всегда должны смотреть и проверять такие предупреждения, генерируемые компилятором.

предупреждение: формат "% p" ожидает тип "void *", но аргумент 2 имеет тип "void (C :: *) ()"

0 голосов
/ 05 октября 2011

Результаты sizeof для данного типа никогда не меняются.(По крайней мере, для соответствующей программы на C ++. Я считаю, что g ++ поддерживает VLA в C ++ как расширение, и sizeof объект, содержащий VLA, может измениться.) Что касается ваших явных вопросов:

printf( "%p\n", g2 );

- неопределенное поведение.Вы передаете указатель на член в выходной форматер, который требует void*.(Я полагаю, что g ++ предупредит об этом, по крайней мере, с некоторыми опциями.) Вы можете получить что угодно (включая сбой программы).Указатели для членов не void* и не могут быть преобразованы в void*.

cout << g2;

Не могу поверить, что это компилируется.

cout << sizeof(g2) << endl;

sizeof(g2) возвращает 8, потому что это размер указателя на член в вашей системе.

cout << sizeof(C) << endl;

Печатает 14, потому что это шестнадцатеричный размер объекта типа C в вашей системе.Другими словами, sizeof(C) равно 20. Так как вы установили вывод для hex и никогда не сбрасывали его, вывод является шестнадцатеричным.

...