Как мне узнать реальный размер моего класса C++?

StackOverflow https://stackoverflow.com/questions/2412971

  •  18-09-2019
  •  | 
  •  

Вопрос

Я работаю над домашним заданием, в котором мне нужно использовать массивы символов вместо строк и qsort/bsearch.В моем призыве к поиску ниже я знать Я передаю неправильный размер Entry, но не знаю, как получить реальный размер, и поэтому моя функция CompareEntries не находит нужные объекты.

Может ли кто-нибудь помочь мне понять, чего мне не хватает?

#include  <iostream>

using  namespace  std;


typedef Entry*  EntryPtr;
class  Dictionary
{
    public  :
        Dictionary( const char  *filename );
        ~Dictionary();
        const char  *lookupDefinition( const char  *word );

    private  :
        int m_numEntries;
        EntryPtr *m_entries;
        static int compareEntries(const void *leftSide, const void *rightSide);
};

int Dictionary::compareEntries(const void *leftSide, const void *rightSide)
{
    EntryPtr lside = (EntryPtr) leftSide;
    EntryPtr rside = (EntryPtr) rightSide;

    return strcmp(lside->Word, rside->Word);
}

const char *Dictionary::lookupDefinition(const char *word)
{
    if (m_numEntries == 0)
        return 0;

    EntryPtr result = (EntryPtr) bsearch(word, m_entries, 
        m_numEntries, sizeof(m_entries[0]), Dictionary::compareEntries);

    return result->Definition;
}

class Entry
{
        public:
                Entry(const char *line);
                char *Word;
                char *Definition;
};

int  main()
{
    Dictionary  dict( "C:\\path\\file.txt" );
    dict.lookupDefinition("chair");
    return  0;
}
Это было полезно?

Решение

Почему не sizeof(Entry) работа?

Снова изменилось - я думаю, размер должен соответствовать размеру указателя....

EntryPtr tmp = new Entry("");
tmp->Word = word;

EntryPtr result = (EntryPtr) bsearch(tmp, m_entries, 
        m_numEntries, sizeof(EntryPtr), Dictionary::compareEntries);

Другие советы

Проблема в том, что функция сравнения, используемая в bsearch надеется word быть типа Entry* (или m_entries быть типа char**).

Ты знаешь это bsearch требует отсортированного ввода, верно?

sizeof(m_entries[0]) мне кажется совершенно нормально.

Редактировать:Теперь я вижу проблему.Ваш класс Dictionary содержит массив указателей.Проблема заключается в функции CompareEntries, где вы приводите переданные указатели к EntryPtr;вам нужно привести их к EntryPtr * вместо.

Редактировать 2:Как указывает Амит Кумар, ты также необходимо изменить ключевой параметр, который вы отправляете в bsearch, или вам нужно понять, что указатели, которые вы получаете в CompareEntries, не указывают на одни и те же типы и потребуют двух разных приведения типов.

sizeof(Entry) будет работать.В большинстве случаев sizeof следует использовать для типа, а не для экземпляра.

размер(Запись)

предпочтительнее

Запись е;
размер(е);

или

Запись* е;
размер(*е);

все дают один и тот же результат.

#include "stdio.h"
class Entry {
  double e;
  int i;
};
int main() {
  Entry e;
  printf("%d\n", sizeof(e));
  printf("%d\n", sizeof(Entry));
  printf("%d\n", sizeof(*(&e)));
  return 0;
}

Прочтите руководство осторожно.

Краткое изложение замечаний, высказанных другими, а также еще несколько вопросов:

  • Ваше использование размер верно.

  • Вам следует передать указатель на запись, содержащую ключ, который вы хотите найти. На самом деле ключ может быть любым, и он будет передан в функцию сравнения в качестве первого аргумента, и вам просто нужно привести оба аргумента к правильным типам.(Функция сравнения по-прежнему должна соответствовать порядку, в котором были отсортированы элементы.)

  • Приведения в функции сравнения неверны.Функция сравнения получает указатель на элемент (который в вашем случае является указателем на Entry, следовательно, функция сравнения получает указатели на указатели на Entry).

  • Вы приводите результат к неправильному типу.И снова функция возвращает указатель на элемент массива (указатель на указатель на Entry).

  • Вы не проверяете, равен ли результат NULL, если ключа там нет.

  • Вероятно, вы могли бы отказаться от одного уровня косвенности (вам действительно нужен массив указателей вместо массива записей?)

  • Вы должны воспринимать это как хороший пример того, что люди имеют в виду, когда говорят о достоинствах типовой безопасности:в вашем коде практически все типы перепутаны и вы делаете неправильные действия с неправильными типами, но ни одной жалобы со стороны компилятора.Вот что ты получишь, если возишься с void*, если только вы точно не знаете, что делаете.

Забавы ради: имея массив указателей, для получения результата требуется нелепое количество косвенных действий:

#include <cstdlib>
#include <string>
#include <iostream>

int compare_string(const void* a, const void* b)
{
    return ((const std::string*)a)->compare(**(const std::string**)b);
}

int main()
{
    std::string a("a"), b("b"), c("c");
    std::string* array[3] = { &a, &b, &c };
    std::string key = "b";
    std::string** result = (std::string**)bsearch(&key, array, 3, sizeof(std::string*), compare_string);
    if (result) std::cout << **result << '\n';
}

ИМХО, для реализации собственного типобезопасного поиска потребуется меньше времени, чем для того, чтобы во всем этом разобраться, протестировать и отладить.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top