Наконец в C++

Заменив это:

self.__ui.tableView.clearSelection()
self.__ui.tableView.selectRow(previous.row())

этим:

QtCore.QTimer.singleShot(0.00001, lambda: self.__ui.tableView.selectRow(previous.row()))

дали желаемый результат

11
задан Tamara Wijsman 24 December 2008 в 02:15
поделиться

6 ответов

Стандартный ответ должен использовать некоторый вариант сокращенного RAII resource-allocation-is-initialization. В основном Вы создаете переменную, которая имеет тот же объем как блок, который был бы в блоке перед наконец, затем выполнил бы в работе наконец блок в деструкторе объектов.

try {
   // Some work
}
finally {
   // Cleanup code
}

становится

class Cleanup
{
public:
    ~Cleanup()
    {
        // Cleanup code
    }
}

Cleanup cleanupObj;

// Some work.

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

std::unique_ptr<Object> obj(new Object());

или современный C++

auto obj = std::make_unique<Object>();

Неважно, какие исключения выдаются, объект будет разрушен. При возвращении к RAII в этом случае распределение ресурсов выделяет память для Объекта и создает его, и инициализация является инициализацией unique_ptr.

28
ответ дан 3 December 2019 в 00:59
поделиться

Нет. Стандартный способ создать наконец как путь состоит в том, чтобы разделить проблемы (http://en.wikipedia.org/wiki/Separation_of_concerns) и сделать объекты, которые используются в блоке попытки, автоматически высвобождают средства в их деструкторе (названный "Объем Связанное управление ресурсами"). Начиная с деструкторов, выполненных детерминировано, в отличие от этого, в Java, можно полагаться на них для чистки безопасно. Таким образом, объекты, что aquired ресурс также очистит ресурс.

Одним путем, который является особенным, является динамическое выделение памяти. Так как Вы - один aquiring ресурс, необходимо вымыться снова. Здесь, интеллектуальные указатели могут использоваться.

try {
    // auto_ptr will release the memory safely upon an exception or normal 
    // flow out of the block. Notice we use the "const auto_ptr idiom".
    // http://www.gotw.ca/publications/using_auto_ptr_effectively.htm
    std::auto_ptr<A> const aptr(new A);
} 
// catch...
11
ответ дан 3 December 2019 в 00:59
поделиться

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

template<typename T>
struct MyDeletable {
    explicit MyDeletable(T *ptr) : ptr_(ptr) { }
    ~MyDeleteable() { delete ptr_; }
private:
    T *ptr_;
    MyDeletable(const MyDeletable &);
    MyDeletable &operator=(const MyDeletable &);
};

void myfunction() {
    // it's generally recommended that these two be done on one line.
    // But it's possible to overdo that, and accidentally write
    // exception-unsafe code if there are multiple parameters involved.
    // So by all means make it a one-liner, but never forget that there are
    // two distinct steps, and the second one must be nothrow.
    Object *myObject = new Object();
    MyDeletable<Object> deleter(myObject);

    // do something with my object

    return;
}

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

Попытка... ловит подход, вероятно, не будет работать хорошо перед лицом эксплуатационного программирования. Блок УБОРКИ, как гарантируют, не будет выполнен: например, если "делают что-то", кодируют возвраты рано, или так или иначе бросает что-то, что не является Исключением. С другой стороны, деструктор "средства удаления" в моем коде, как гарантируют, будет выполнен в обоих тех случаях (хотя не, если программа завершится).

4
ответ дан 3 December 2019 в 00:59
поделиться

Мой совет: не пытайтесь эмулировать поведение попытки наконец пункт в C++. Просто используйте RAII вместо этого. Вы будете жить более счастливые.

3
ответ дан 3 December 2019 в 00:59
поделиться

Принятие Вас надеется удалять указатель myObject и избегать утечек памяти, Ваш код все еще может не сделать это, если существует оператор "возврата" в коде, где Вы говорите // Do something with myObject. (Я предполагаю, что реальный код был бы здесь),

Методы RAII имеют соответствующее действие, которое эквивалентно "наконец" блок в деструкторе конкретного объекта:

class ResourceNeedingCleanup
{
  private:
    void cleanup(); // action to run at end
  public:
    ResourceNeedingCleanup( /*args here*/) {}
    ~ResourceNeedingCleanup() { cleanup(); }  

    void MethodThatMightThrowException();
};

typedef boost::shared_ptr<ResourceNeedingCleanup> ResourceNeedingCleanupPtr;
// ref-counted smart pointer


class SomeObjectThatMightKeepReferencesToResources
{
   ResourceNeedingCleanupPtr pR;

   void maybeSaveACopy(ResourceNeedingCleanupPtr& p)
   {
      if ( /* some condition is met */ )
         pR = p;
   }
};

// somewhere else in the code:
void MyFunction(SomeObjectThatMightKeepReferencesToResources& O)
{
   ResourceNeedingCleanup R1( /*parameters*/) ;
   shared_ptr<ResourceNeedingCleanup> pR2 = 
        new ResourceNeedingCleanup( /*parameters*/ );
   try
   {
      R1.MethodThatMightThrowException();
      pR2->MethodThatMightThrowException();
      O->maybeSaveACopy(pR2);
   }
   catch ( /* something */ )
   {
      /* something */
   }

   // when we exit this block, R1 goes out of scope and executes its destructor
   // which calls cleanup() whether or not an exception is thrown.
   // pR2 goes out of scope. This is a shared reference-counted pointer. 
   // If O does not save a copy of pR2, then pR2 will be deleted automatically
   // at this point. Otherwise, pR2 will be deleted automatically whenever
   // O's destructor is called or O releases its ownership of pR2 and the
   // reference count goes to zero.
}

Я думаю, что у меня есть корректная семантика; я не использовал shared_ptr очень сам, но я предпочитаю его auto_ptr <> - указатель на объект может только "принадлежать" одному auto_ptr <>. Я использовал CComPtr COM и вариант его, что я записал меня для "регулярного" (non-COM) объекты, который подобен shared_ptr <>, но имеет Присоединение () и Отсоединение () для передачи указателей от одного интеллектуального указателя до другого.

2
ответ дан 3 December 2019 в 00:59
поделиться

Непосредственно отвечать на Ваш вопрос, нет.

Это - умный способ реализовать ту функциональность, но это не надежно. Один путь, который приведет Вас к сбою, состоит в том, если Ваш "делают что-то" код, выдает исключение, которое не получено из Exception. В этом случае Вы никогда не будете delete myObject.

Здесь существует более важный текущий вопрос, и это - методологии, принятые программистами какого-то конкретного языка. Причина, которую Вы слышите о RAII, состоит в том, потому что программисты с намного большим опытом, чем Вы или я нашел, что в домене программирования на C++, что методология надежна. Можно полагаться на других программистов, использующих его, и другие программисты захотят полагаться на Вас использующий его.

2
ответ дан 3 December 2019 в 00:59
поделиться
Другие вопросы по тегам:

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