Еще одна опция:
var someArray = [...];
function generateSortFn(prop, reverse) {
return function (a, b) {
if (a[prop] < b[prop]) return reverse ? 1 : -1;
if (a[prop] > b[prop]) return reverse ? -1 : 1;
return 0;
};
}
someArray.sort(generateSortFn('name', true));
сортирует по возрастанию по умолчанию.
Деструктор для таких временных файлов называют в конце полного выражения. Это - самое внешнее выражение, которое не является частью никакого другого выражения. Это находится в Вашем случае после функциональных возвратов, и значение оценено. Так, это будет работать все хорошие.
Это на самом деле, что делает шаблонную работу выражения: Они могут держать ссылки на такие временные файлы в выражении как
e = a + b * c / d
, поскольку каждый временный файл продлится, пока выражение
x = y
не оценено полностью. Это вполне кратко описано в 12.2 Temporary objects
в Стандарте.
StringBuffer в пределах GetString. Это должно быть уничтожено в конце объема GetString (т.е. когда это возвращается). Кроме того, я не полагаю, что C++ будет гарантии, что переменная будет существовать, пока существует ссылка.
следующее должно скомпилировать:
Object* obj = new Object;
Object& ref = &(*obj);
delete obj;
ответ litb точен. Время жизни временного объекта (также известный как rvalue) связывается с выражением, и деструктор для временного объекта называют в конце полного выражения и когда деструктор на StringBuffer назовут, деструктор на m_buffer также назовут, но не деструктор на m_str, так как это - ссылка.
Примечание, что C++ 0x изменяет вещи просто немного, потому что это добавляет rvalue ссылки и семантику перемещения. По существу при помощи rvalue параметра ссылки (записанный нотами с & &) я могу 'переместить' rvalue в функцию (вместо того, чтобы копировать его), и время жизни rvalue может быть связано с объектом, который это перемещает в, не выражение. Существует действительно хорошее сообщение в блоге от команды MSVC на этом обходы через это в мельчайших подробностях , и я поощряю людей читать его.
педагогическим примером для движущегося rvalue's являются временные строки, и я покажу присвоение в конструкторе. Если у меня есть класс MyType, который содержит строковую членскую переменную, он может быть инициализирован с rvalue в конструкторе как так:
class MyType{
const std::string m_name;
public:
MyType(const std::string&& name):m_name(name){};
}
Это хорошо потому что, когда я объявляю экземпляр этого класса с временным объектом:
void foo(){
MyType instance("hello");
}
то, что происходит, - то, что мы стараемся не копировать и уничтожать временный объект, и "привет" помещается непосредственно в членской переменной экземпляра класса владения. Если объект является более тяжелым весом, чем 'строка' тогда, дополнительная копия и вызов деструктора могут быть значительными.
Я записал почти точно тот же класс:
template <class C>
class _StringBuffer
{
typename std::basic_string<C> &m_str;
typename std::vector<C> m_buffer;
public:
_StringBuffer(std::basic_string<C> &str, size_t nSize)
: m_str(str), m_buffer(nSize + 1) { get()[nSize] = (C)0; }
~_StringBuffer()
{ commit(); }
C *get()
{ return &(m_buffer[0]); }
operator C *()
{ return get(); }
void commit()
{
if (m_buffer.size() != 0)
{
size_t l = std::char_traits<C>::length(get());
m_str.assign(get(), l);
m_buffer.resize(0);
}
}
void abort()
{ m_buffer.resize(0); }
};
template <class C>
inline _StringBuffer<C> StringBuffer(typename std::basic_string<C> &str, size_t nSize)
{ return _StringBuffer<C>(str, nSize); }
До стандарта каждый компилятор сделал это по-другому. Я полагаю, что старый Аннотируемый Справочник для C++ определил, что временные файлы должны вымыться в конце объема, таким образом, некоторые компиляторы сделали это. Уже в 2003 я нашел, что поведение все еще существовало по умолчанию на компиляторе C++ Forte Sun, таким образом, StringBuffer не работал. Но я был бы удивлен, был ли какой-либо текущий компилятор все еще поврежденным.