Что означает сохранение ресурса как инвариантного класса в RAII?

Что означает, что сохранение ресурса является инвариантом класса в RAII?

На странице Википедии RAII говорится:

В RAII хранение ресурса является инвариантом класса и привязано к времени жизни объекта: выделение (получение) ресурсов выполняется во время создания объекта (в частности, инициализации) конструктором, а освобождение ресурса (освобождение) выполняется во время уничтожения объекта (в частности, финализация) деструктором.

На примере D language мы можем легко понять, что означает Class Invariant:

class Date {
  int day;
  int hour;

  invariant() {
    assert(1 <= day && day <= 31);
    assert(0 <= hour && hour < 24);
  }
}

Это ограничение, относящееся к тому, что может удерживать поле класса, чтобы считаться допустимым состоянием. Однако что это значит для удержания ресурса? Означает ли это, что ресурс принадлежит мне и будет добываться с момента его создания конструктором до его уничтожения де деструтором?


person user    schedule 21.02.2017    source источник
comment
Для всех остальных я обнаружил, что эта ссылка лучше объясняет RAII: tomdalling.com/blog/software-design/   -  person user    schedule 21.02.2017


Ответы (1)


Означает ли это, что ресурс принадлежит мне и будет добываться с момента его создания конструктором до его уничтожения де деструтором?

В правильно спроектированной программе это так, но концепция владения не применяется в C ++.

Легко «прострелить себе ногу» и отдать ресурс какому-то другому объекту. Например, когда ресурс является указателем, вы можете случайно поделиться им между объектами, например:

struct A
{
    int some_variable;
};

struct A_holder
{
    A* ptr;
    A_holder()
    {
        ptr = new A();
    }
    ~A_holder()
    {
        delete ptr;
    }
};

int main()
{

    {
        A_holder a_holder;
        auto another_A_holder = a_holder;
    }
   //error because delete is called twice:
   //first on A_holder's pointer and a second time on another_A_holder's pointer
    return 0;
}

См. https://rmf.io/cxx11/rule-of-zero для правило нуля

person Mikhail    schedule 21.02.2017
comment
стоит добавить deleteing конструктор копирования и оператор присваивания в качестве простой защиты от этого - person user4581301; 21.02.2017
comment
@ user4581301 Ага, мой любимый способ - унаследовать от boost :: noncopyable - person Mikhail; 21.02.2017
comment
это возможно, если вы следуете правилу пяти / правилу нуля. измените ptr на unique_ptr, устранит проблему. - person Bryan Chen; 21.02.2017
comment
@BryanChen Да, но это не то же самое, что язык, требующий этого. Подумайте о заимствовании из ржавчины. - person Mikhail; 21.02.2017
comment
Но ваш стандарт кода / экспертная оценка могут обеспечить его соблюдение. Особенно, когда в базе кода, где умные указатели используются повсюду, необработанный указатель очень цепляет. - person Bryan Chen; 21.02.2017
comment
Итак, чтобы использовать RAII на C ++, я должен удалить конструктор копирования и оператор присваивания, никогда не передавать свои ресурсы кому-либо еще? Следовательно, Правило трех и Правило пяти стало Правилом двух и Правилом четырех? - person user; 21.02.2017
comment
@addons_zz Вам нужно правило нуля. Большинство вещей не должны владеть ресурсами. Вот ссылка rmf.io/cxx11/rule-of-zero - person Mikhail; 21.02.2017
comment
Тогда я использую Правило 3/5 только тогда, когда я не использую надлежащее удержание ресурсов RAII. - person user; 21.02.2017
comment
@Mikhail: Большинству вещей не должны принадлежать ресурсы. Лучше сказать, что большинству вещей не должны напрямую принадлежать ресурсы. - person Nicol Bolas; 21.02.2017
comment
@addons_zz Вы должны использовать правило 3/5 только при написании исключительно особого и редкого класса, который будет напрямую удерживать ресурс. Для большинства программ этот вид класса уже реализован в виде std :: vector ‹›. - person Mikhail; 21.02.2017