Как мне узнать реальный размер моего класса C++?
Вопрос
Я работаю над домашним заданием, в котором мне нужно использовать массивы символов вместо строк и 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';
}
ИМХО, для реализации собственного типобезопасного поиска потребуется меньше времени, чем для того, чтобы во всем этом разобраться, протестировать и отладить.