Вот как я решил эту проблему в нашем демонстрационном приложении для книги O'Reilly Ember.js: https://github.com/emberjsbook .
Вы можете увидеть полный источник здесь: https://github.com/emberjsbook/rocknrollcall
В представлении:
{{#if artistsIsChecked}}
{{#if artists.length}}
Artists
{{#each artists}}
- {{name}}
{{/each}}
{{/if}}
{{/if}}
И контроллер :
App.SearchResultsController = Em.ObjectController.extend({
actions: {
viewedArtist: function(enid) {
this.transitionToRoute('artist', enid);
},
viewedSong: function(sid) {
this.transitionToRoute('song', sid);
}
},
needs: ['artists', 'songs'],
artistsIsChecked: true,
songsIsChecked: true,
artists: [],
songs: []
});
Да C ++ решает проблему с помощью так называемой семантики перемещения .
В основном он позволяет одному объекту взять на себя внутреннее представление другого объекта, если этот объект является временный. Вместо того, чтобы копировать каждый байт в строке, например, через конструктор копирования, вы часто можете просто позволить целевой строке принимать внутреннее представление исходной строки. Это разрешено только в том случае, если источником является значение R.
Это делается путем введения конструктора перемещения . Это конструктор, в котором вы знаете, что объект src является временным и исчезает. Следовательно, приемник может взять на себя внутреннее представление объекта src.
То же самое верно и для операторов присваивания перемещения .
Чтобы отличать конструктор копирования от конструктора перемещения, в языке введены ссылки на rvalue . Класс определяет свой конструктор перемещения так, чтобы он принимал ссылку rvalue , которая будет привязана только к rvalue (временным). Итак, мой класс определил бы что-то вроде:
class CMyString
{
private:
char* rawStr;
public:
// move constructor bound to rvalues
CMyString(CMyString&& srcStr)
{
rawStr = srcStr.rawStr
srcStr.rawStr = NULL;
}
// move assignment operator
CMyString& operator=(CMyString&& srcStr)
{
if(rawStr != srcStr.rawStr) // protect against self assignment
{
delete[] rawStr;
rawStr = srcStr.rawStr
srcStr.rawStr = NULL;
}
return *this;
}
~CMyString()
{
delete [] rawStr;
}
}
Здесь - очень хорошая и подробная статья о семантике перемещения и синтаксисе, который позволяет вам это делать.
Извините - вы не можете заявить как факт, что string concat = accumulate (v.begin (), v.end (), string (""));
должен перераспределить. Конечно же, простая реализация. Но компиляторам здесь позволено поступать правильно.
Это уже имеет место в C ++ 98, а C ++ 0x по-прежнему допускает как интеллектуальные, так и глупые реализации. Тем не менее, семантика перемещения упростит интеллектуальные реализации.
Одним из преимуществ повышения производительности будут обобщенные константные выражения, которые вводятся ключевым словом constexpr.
constexpr int returnSomething() {return 40;}
int avalue[returnSomething() + 2];
Это недопустимый код C ++, потому что returnSomething () + 2 не является постоянным выражением.
Но с помощью ключевого слова constexpr C ++ 0x может сообщить компилятору, что выражение является константой времени компиляции.