Действительные фьючерсы против построенных по умолчанию фьючерсов

Я изучаю фьючерсы в своем классе параллельного программирования. Мой профессор заявил об этом на своих слайдах:

"Valid" futures are future objects associated to a 
shared state, and are constructed by calling one of the following functions:

async
promise::get_future
packaged_task::get_future

будущие объекты полезны только тогда, когда они действительны. Будущие объекты, построенные по умолчанию, недействительны (если только перемещение не назначило допустимое будущее).

Я не могу понять смысл вышеизложенного, особенно часть «если не будет назначено действительное будущее». Может ли кто-нибудь объяснить это простыми словами и, возможно, показать пример кода?


person Flame of udun    schedule 31.10.2016    source источник
comment
Странность std::future заключается в том, что ни один из его конструкторов или методы могут сделать будущий объект действительным.   -  person Raedwald    schedule 25.04.2018


Ответы (1)


Как указано в конструкторе std::future:

Будущие объекты, построенные по умолчанию, недействительны

Это просто означает вызов конструктора по умолчанию для объекта, например:

std::future<int> f;

Это вызовет конструктор №1, в котором указано:

Конструктор по умолчанию. Создает std::future без общего состояния. После строительства, valid() == false.

Что касается другой части:

(если перемещение не назначено действительным будущим)

Здесь имеется в виду, что будет вызван конструктор перемещения (future( future&& other ) #2), в котором указано:

Переместить конструктор. Создает std::future с общим состоянием other, используя семантику перемещения. После строительства other.valid() == false.

По сути, состояние other в этом конструкторе перемещено в this. Это означает, что если other.valid() == true, то после возврата конструктора перемещения other.valid() будет false, а this.valid() будет true. Если other.valid() было false в начале, то в итоге оба получат false.

std::future<int> fut; // fut.valid() == false, default constructor

std::future<int> valid_fut = std::async(std::launch::async, [](){ return 42; }); // obtain a valid std::future..
// valid_fut.valid() == true here

//now move valid_fut into new_fut
std::future<int> new_fut(std::move(valid_fut));
// new_fut.valid() == true
// valid_fut.valid() == false

Обобщить:

  • Вызов конструктора по умолчанию для std::future приведет к valid() == false. Всегда.

  • Вызов конструктора перемещения для std::future приведет к valid() == true только, если other.valid() было true перед перемещением из него. Ложь в противном случае.

person Hatted Rooster    schedule 31.10.2016
comment
Небольшая загвоздка: конструктор перемещения не обязательно вступает в игру. Буквально они означают, что если в конце вашего примера вы должны были сделать fut = std::move(new_fut);, fut будет действительным. Это то назначение движения, о котором они говорят. (На самом деле вы также показываете это при назначении valid_fut, хотя компилятор попытается обработать это как конструктор перемещения, а не присваивание перемещения.) - person Daniël van den Berg; 29.04.2021