2015-10-28 8 views
0

Существует простой пример:Передача права собственности (Genie/Вала)

struct MyStruct 
    a: int 
    b: int 

def my_proc(): unowned list of MyStruct 
    var result = new list of MyStruct 
    var my_struct = MyStruct() 
    for var i = 1 to 10 
     my_struct.a = i 
     my_struct.b = i*i 
     result.add(my_struct) 
    return result 

init 
    pass 

в случае компиляции этого кода, возникает ошибка: «Локальная переменная с сильной ссылкой, используемой в качестве возвращаемого значения и метод обратного типа не было объявлено о передаче права собственности ». Как изменить код, который был успешно выполнен?

ответ

0

джин список действительно в «маскировке», который является типом класса А Gee.List<T>, так что это будет подсчет ссылок.

Также переменная типа var в настоящее время всегда принадлежит переменной (об этом сообщается в отчете об ошибках Vala).

Так result сильная ссылка на экземпляр класса. Вы не можете вернуть это как неопубликованную ссылку.

Я настоятельно советую вам использовать класс вместо структуры для MyStruct.

В противном случае вы будете иметь проблемы управления памятью (не структуры являются подсчет ссылок).

Вам не придется беспокоиться о копировании и собственности, то:

class MyStruct 
    a: int 
    b: int 

def my_proc(): list of MyStruct 
    var result = new list of MyStruct 
    for var i = 1 to 10 
     var my_struct = new MyStruct() 
     my_struct.a = i 
     my_struct.b = i*i 
     result.add(my_struct) 
    return result 

init 
    pass 

Edit: Если вы хотите, чтобы список содержит несколько значений, вы должны выделить my_struct внутри цикла, как хорошо! Я обновил свой код, чтобы отразить это.

+1

Выражения Структуры вызывают проблемы с управлением памятью, потому что они не относятся к подсчету, что может показаться ошибочным. Я знаю, что контекст является примером «MyStruct», но утверждение подразумевает, что всегда будут проблемы с структурами. Структуры в Vala/Genie, однако, являются стеками, выделенными и скопированными при назначении. В то время как классы выделены в кучу. Стек будет меньше, чем куча, и стратегия распределения памяти будет проще и быстрее, но пока различия будут понятны, достаточно, чтобы структуры Genie были полезны. – AlThomas

+0

Вы абсолютно правы, «проблемы с управлением памятью» являются слишком обобщенными, но ваш ответ теперь хорошо дополняет мой. –

1

Там должно быть по крайней мере одна ссылка на объект в любой момент времени. Здесь вы создаете переменную result, которая имеет ссылку на список. Когда вы вернете его, вы настаиваете, что это unowned list of MyStruct. Это означает, что возврат не имеет ссылки, и result выходит за пределы области видимости, поэтому список теперь не имеет ссылок на него и будет освобожден.

Вы эффективно возвращаете болтающуюся ссылку. Либо верните list of MyStruct, так что вызывающий объект имеет ссылку или поместит копию в какое-либо общее состояние (глобальная переменная или поле).

2

Что заставило вас думать, что возвращаемое значение должно быть недействительным?

Если это так, потому что без unowned коммандер Vala дал "error: 'MyStruct' is not a supported generic type argument, use '?' to box value types", то вы можете попробовать list of MyStruct?. Этот «ящик» [1] [2] базовый тип данных C, чтобы он мог использоваться в базовой системе типа GObject.

Если это было из-за того, что вы прочитали учебное пособие и разделы «Слабые ссылки», «Неопубликованные ссылки», «Передача прав собственности» и «Указатели», то я думаю, вы должны просмотреть эти темы в качестве расширенных тем. Я думаю, что они должны быть перемещены в какой-то момент на отдельную страницу для людей, которые хотят копать глубоко в Джини.

Вала компилятор и так Genie, оказывает помощь управления памятью. Это означает, что все заботится о вас в фоновом режиме. Компилятор Vala имеет разумное поведение по умолчанию, поэтому вам не нужно ничего менять.

Как программист Genie, вы должны знать типы с нулевым значением для взаимодействия с библиотеками C, и подсчет ссылок может создавать утечки памяти при создании циклических ссылок [3].Помимо этого, посмотрите на темы в этом разделе учебника Genie, как для людей, которые действительно хотят глубоко понять, как работает Genie и что-то исправить.

Структуры можно рассматривать как предвестник объектов. Структуры являются составным типом данных. Память для структур в Vala/Genie обрабатывается компилятором C в стеке [4]. Это потенциально дает им преимущество в производительности. Однако, как правило, лучше использовать класс для сложных типов данных, поскольку они лучше подходят для базовой системы типа GObject. Однако вы можете использовать структуры, если вы пытаетесь сильно оптимизировать некоторый код для скорости [5] или интерфейс с библиотекой C, которая использует структуры.

Итак, короткий ответ идет с решением Йенса по использованию класса, если у вас нет веской причины.

[1] - https://developer.gnome.org/gobject/stable/gobject-Boxed-Types.html

[2] - Vala interface generics compiler error

[3] - https://wiki.gnome.org/Projects/Vala/ReferenceHandling

[4] - https://wiki.gnome.org/Projects/Vala/Tutorial#Structs

[5] - http://zee-nix.blogspot.co.uk/2008/09/think-before-you-create-gobjects.html

+0

Я только что протестировал версию 'struct MyStruct? 'И был удивлен, увидев, что libgee прекрасно справляется с разрушением памяти структуры. –

+0

Полезно знать, что он также должен работать для таких вещей, как 'list uint64?' И 'struct', и' uint64' являются примерами типов значений, поэтому не подсчитываются ссылки, а выделяются в стек компилятором C – AlThomas

Смежные вопросы