Гарантируемое время жизни временного файла в C++?

Еще одна опция:

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));

сортирует по возрастанию по умолчанию.

94
задан Mark Ransom 25 February 2009 в 05:58
поделиться

5 ответов

Деструктор для таких временных файлов называют в конце полного выражения. Это - самое внешнее выражение, которое не является частью никакого другого выражения. Это находится в Вашем случае после функциональных возвратов, и значение оценено. Так, это будет работать все хорошие.

Это на самом деле, что делает шаблонную работу выражения: Они могут держать ссылки на такие временные файлы в выражении как

e = a + b * c / d

, поскольку каждый временный файл продлится, пока выражение

x = y

не оценено полностью. Это вполне кратко описано в 12.2 Temporary objects в Стандарте.

103
ответ дан Johannes Schaub - litb 5 November 2019 в 13:18
поделиться

После вызова к возвратам GetString.

3
ответ дан David Segonds 5 November 2019 в 13:18
поделиться

StringBuffer в пределах GetString. Это должно быть уничтожено в конце объема GetString (т.е. когда это возвращается). Кроме того, я не полагаю, что C++ будет гарантии, что переменная будет существовать, пока существует ссылка.

следующее должно скомпилировать:

Object* obj = new Object;
Object& ref = &(*obj);
delete obj;
2
ответ дан BigSandwich 5 November 2019 в 13:18
поделиться

ответ 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");
}

то, что происходит, - то, что мы стараемся не копировать и уничтожать временный объект, и "привет" помещается непосредственно в членской переменной экземпляра класса владения. Если объект является более тяжелым весом, чем 'строка' тогда, дополнительная копия и вызов деструктора могут быть значительными.

16
ответ дан Marco A. 5 November 2019 в 13:18
поделиться

Я записал почти точно тот же класс:

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 не работал. Но я был бы удивлен, был ли какой-либо текущий компилятор все еще поврежденным.

3
ответ дан Daniel Earwicker 5 November 2019 в 13:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: