Кажется довольно ясным, что это, как предполагается, настраивает вещи.
__attribute__
функция? Макрос? Синтаксис?__attribute__((destructor))
выполненный?__attribute__((constructor))
static void initialize_navigationBarImages() {
navigationBarImages = [[NSMutableDictionary alloc] init];
}
__attribute__((destructor))
static void destroy_navigationBarImages() {
[navigationBarImages release];
}
Существует два способа реализации службы отображения, подобных описанному вами.
Клиенты отправляют глобально уникальные идентификаторы
Насколько мне известно, 1. следует пытаться только с помощью Guid
, если только вы не разработаете аналогичное средство для передачи достаточно четкой информации в короткий поток байтов. В любом случае, если у вас есть поток байтов, которые представляют глобально уникальный идентификатор, вы можете сделать что-то подобное
// source is either a Guid, or some other globally unique byte stream
byte[] bytes = Guid.NewGuid ().ToByteArray ();
string base64String = Convert.ToBase64String (bytes).Trim ("=");
, чтобы получить считываемую пользователем последовательность алфавитно-цифровых чисел, которая выглядит случайной, но избегает конфликтов, присущих другим случайным схемам. Guid
содержит 16 байт или 128 бит, что соответствует приблизительно 19 символам для полной кодировки Base64.
Преимущество этого подхода в том, что клиенты могут генерировать свои собственные крошечные Uris без центрального органа. Минусом является большая длина, если вы катитесь с Guid
или реализуете свой собственный глобально уникальный поток байтов, который - давайте посмотрим правде в глаза - склонен к ошибкам.
Если вы действительно идете по этому маршруту, рассмотрите глобально уникальные потоки байтов Google или такие. О, и ДЕРЖИТЕСЬ ПОДАЛЬШЕ ОТ СЛУЧАЙНЫХ БАЙТОВ , иначе вам придется построить разрешение коллизий ПОВЕРХ вашего крошечного генератора URI.
Сервер генерирует глобальные уникальные идентификаторы
Опять же, основное преимущество вышеизложенного состоит в том, что Клиент может генерировать свой Uris априори . Особенно удобно, если вы собираетесь отправить длительный запрос, который вы хотите проверить. Это может не иметь особого отношения к вашей ситуации и может дать лишь ограниченную ценность.
Таким образом, если не считать серверно-ориентированного подхода, в котором единый орган власти генерирует и выдает идентификаторы, может быть более привлекательным. Если это выбранный маршрут, то вопрос только в том, как долго вы хотите ваш URI?
Предполагая желаемую длину 5 символов, и допустим, вы идете с Base64 кодировкой, каждый идентификатор может представлять до 5 символов на 7 бит на символ равно 35 бит или 2 ^ 35 [34 359 738 368] различных значений. Это довольно большой домен. *
Тогда возникает вопрос о возврате значения для данного представления. Вероятно, есть много способов сделать это, но я бы пошел с чем-то вроде этого,
Усовершенствования или оптимизации могут включать
Вывод
Итог:вы хотите гарантировать уникальность - так что коллизии являются большим нет-нет.
* = 34 359 738 368 - размер необработанного домена, это все идентификаторы от 0 длины до 5 длины. Если вы заинтересованы в ограничении всех идентификаторов минимальной и максимальной длиной 5, то ваш домен выглядит так, что все идентификаторы длиной от 0 до 5 (2 ^ 35) меньше, чем все идентификаторы длиной от 0 до 4 (2 ^ 28) составляет от 2 ^ 35 до 2 ^ 28 = 34 091 302 912, что все еще довольно велико:)
-121--432â6-Вы говорите:
Для другого можно вернуть списки из функций, даже если вы никогда передан в списке при вызове функция и даже несмотря на то, что функция не содержит конструктор List, Например,
x = strsplit(LETTERS[1:10], "") # passing in an object of type 'character'
class(x)
# => 'list'
И я полагаю, вы предполагаете, что это проблема (?). Я здесь, чтобы сказать вам, почему это не проблема: -). Ваш пример немного прост, так как при разделении строки имеется список с элементами длиной 1 элемента, поэтому известно, что x [[1]]
совпадает с unlist (x) [1]
. Но что, если результат strsplit
вернул результаты различной длины в каждой ячейке. Просто вернуть вектор (против списка) совсем не получится.
Например:
stuff <- c("You, me, and dupree", "You me, and dupree",
"He ran away, but not very far, and not very fast")
x <- strsplit(stuff, ",")
xx <- unlist(strsplit(stuff, ","))
В первом случае ( x
: который возвращает список) можно указать, какой была 2-я «часть» 3-й строки, например x [[3]] [2]
. Как вы могли бы сделать то же самое с помощью xx
теперь, когда результаты были «распутаны» ( unlist
-ed)?
Итак, работа конструкторов и деструкторов заключается в том, что файл общих объектов содержит специальные разделы (.ctors и .dtors в ELF), которые содержат ссылки на функции, отмеченные атрибутами конструктора и деструктора соответственно. Когда библиотека загружается/выгружается, программа динамического загрузчика (ld.so или somesuch) проверяет, существуют ли такие разделы, и, если да, вызывает функции, на которые в них ссылаются.
Подумайте об этом, вероятно, в обычном статическом компоновщике есть какая-то похожая магия, так что при запуске/выключении запускается один и тот же код независимо от того, выбирает ли пользователь статическое или динамическое связывание.