Могу ли я завершить область видимости переменной C ++, не заканчивая блок? - PullRequest
3 голосов
/ 25 февраля 2011

Я хотел бы сделать что-то вроде следующего шаблона:

T* const pT = findT();
// Do some work
T* const pT2 = new T( *pT );
// Mutate the object pT2 refers to
delete pT;
// At this point, I want the scope of pT to end.
// I do not want the scope of pT2 to end

Я знаю, что могу закончить область видимости, заканчивая блок, но это заканчивается так:

T* pT2 = 0;
{
    T* const pT = findT();
    // Do some work
    pT2 = new T( *pT );
    // Mutate the object pT2 refers to
    delete pT;
}

Это приводит к тому, что pT2 теряет свой константный квалификатор, потому что я должен назначить его после того, как он объявлен.

Я хочу свой торт и хочу его съесть, я хочу чистую константу и правильная область видимости!

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

Ответы [ 5 ]

4 голосов
/ 25 февраля 2011

Вы можете использовать лямбды:

T* const pT = []() -> T* {
    T* pT;
    // Do whatever the hell you want with pT
    return pT;
}();
3 голосов
/ 25 февраля 2011

Есть ли способ завершить область действия переменной, кроме окончания блока?

Нет.Область действия локальной переменной начинается, когда она объявляется, и заканчивается в конце блока, в котором она объявлена.

Если нет, то планируете ли вы расширить стандарт для его поддержки?

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

0 голосов
/ 18 марта 2019

Вы можете использовать std :: необязательный (или boost :: необязательный ) для точного контроля времени жизни объекта.

Вот пример:

std::optional< ClassA > a(std::in_place, 1); // ClassA constructor is called
std::optional< ClassB > b(std::in_place, 2); // ClassB constructor is called
a.reset(); // ClassA destructor is called
b.reset(); // ClassB destructor is called

К сожалению, имя переменной все еще там, и ее память все еще выделена.

Существует также хитрость для уничтожения строки и освобождения ее памяти (сама переменная все еще там):

std::string my_str;
std::string{}.swap(my_str); // likely to free the memory

Это определено реализацией, поэтому оно может на самом деле не освобождать память, но, скорее всего, это так.

0 голосов
/ 25 февраля 2011

Нет.Однако вы можете использовать следующую идиому, чтобы немного украсить свой пример (хорошо, это субъективно, но эй):

T* p1 = 0;

if (T* const p2 = findT()) {
  p1 = new T( *p2 );
  delete p2;
}
0 голосов
/ 25 февраля 2011

То, что вы называете «блоком» - это еще одно имя в C ++ для «контекста». Это означает , как вы определяете область в C ++.

Другим вариантом здесь является использование std::auto_ptr, которое передает право собственности при назначении. Старый указатель не будет очищен, но фактически будет равен нулю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...