2014-09-02 8 views
0

В качестве примера, у меня есть класс, который я хранящую информацию о бинарных файлах:String pooling/interning - Это хорошая практика?

class car { 
    char car_manufacturer; 
    //other stuff 
}; 

Если значение car_manufacturer является одним из значений:

enum car_manufacturers : char { 
    VOLVO = 0, 
    AUDI, 
    MERCEDES 
}; 

В настоящее время в это пример приложения, пользователь захочет строковое представление своего автопроизводителя, а не числа, поэтому я создаю массив со строковыми представлениями перечислений , где упорядочение массива такое же, как и перечисление, поэтому car_manufacturer может быть используется как индекс массива

std::string car_manufacturers_strings[MERCEDES + 1] = { 
    "Volvo", 
    "Audi", 
    "Mercedes" 
}; 

Так что теперь после загрузки файла и создания car объект из данных, я могу получить марку автомобиля, как строка просто car_manufacturers_strings[car.car_manufacturer];

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

Это хорошая или плохая практика?

+1

Вы можете добавить метод в свой класс, который выполняет именно это. Затем тот факт, что эти строки хранятся в массиве с тем же порядком, что и перечисление производителя, является деталью реализации, которая скрыта от пользователя. – MicroVirus

+0

@MicroVirus Это точно так же, как я реализовал его в своем приложении, а автомобили - аналогия. Фактически, я реализовал эквивалент 'car.get_car_manufacturer_name();' – user3680400

ответ

1

Это довольно стандартная практика предоставления строковых представлений перечислений в виде массива.

Одна точка в том, что:

std::string car_manufacturers_strings[MERCEDES + 1] = { 
    "Volvo", 
    "Audi", 
    "Mercedes" 
}; 

Магазины строковые литералы в двоичном, а также создает копии этих литералов как std::string объектов в динамической фазе инициализации.

Вы можете, как изменить его на:

char const* const car_manufacturers_strings[MERCEDES + 1] = { 
    "Volvo", 
    "Audi", 
    "Mercedes" 
}; 

Так что не излишне создавать эти копии.

+0

> Сохраняет строковые литералы в двоичном формате, а также создает копии этих литералов в виде std :: string объектов на этапе динамической инициализации. Я понятия не имел, что «std :: string» будет делать это, хотя в ретроспективе это имеет прекрасный смысл, учитывая способность std :: string' изменять размер и многое другое. Спасибо! – user3680400

1

я вообще сделать это с помощью функции, вдоль линий:

char const * to_string(car_manufacturers cm) { 
    switch (cm) { 
     #define CASE(CM) case CM: return #CM; 
     CASE(Volvo) 
     CASE(Audi) 
     CASE(Mercedes) 
     #undef CASE 
    } 
    return "Unknown"; // or throw, or whatever 
} 

Преимущества:

  • не нужно преобразовать аргумент в числовой индекс, поэтому он работает с контекстными перечислений без потребность в отвратительном литье;
  • мой компилятор выдает предупреждение, если добавить нумератор без обновления функции (не так хорошо, как удаление дублирования, но, по крайней мере, консистенция исполнение)

Недостатки:

  • switch может (или не может быть) менее эффективны, чем поиск в массиве.
  • Капитализация счетчиков должна соответствовать строкам, поэтому вам необходимо отказаться от фетиша для SHOUTY_CAPS. Некоторые сказали бы, что это хорошо; они, конечно, больно мне глаза.
  • Ewwww! Макросы!
Смежные вопросы