2016-11-18 4 views
1

Я читаю Nicolai M. Josuttis-х 2nd edition of "The C++ Standard Library" covering C++11, где в главе 18: Параллельное, страница 969 и 970 дают пример программы:Можно ли возвращать локальную переменную путем перемещения?

// concurrency/promise1.cpp 
#include <thread> 
#include <future> 
#include <iostream> 
#include <string> 
#include <exception> 
#include <stdexcept> 
#include <functional> 
#include <utility> 
void doSomething (std::promise<std::string>& p) 
{ 
    try { 
     // read character and throw exceptiopn if ’x’ 
     std::cout << "read char (’x’ for exception): "; 
     char c = std::cin.get(); 
     if (c == ’x’) { 
      throw std::runtime_error(std::string("char ")+c+" read"); 
     } 
     ... 
     std::string s = std::string("char ") + c + " processed"; 
     p.set_value(std::move(s)); // store result 
    } 
    catch (...) { 
     p.set_exception(std::current_exception()); // store exception 
    } 
} 

int main() 
{ 
    try { 
     // start thread using a promise to store the outcome 
     std::promise<std::string> p; 
     std::thread t(doSomething,std::ref(p)); 
     t.detach(); 
     ... 
     // create a future to process the outcome 
     std::future<std::string> f(p.get_future()); 
     // process the outcome 
     std::cout << "result: " << f.get() << std::endl; 
    } 
    catch (const std::exception& e) { 
     std::cerr << "EXCEPTION: " << e.what() << std::endl; 
    } 
    catch (...) { 
     std::cerr << "EXCEPTION " << std::endl; 
    } 
} 

Здесь strings является локальной переменной, но переехал, чтобы вернуться.

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

Примечание: этот вопрос отличается от c++11 Return value optimization or move?: этот вопрос о move потенциально опасен, в то время как другой вопрос касается того, активно ли запрещает копирование или разрешает компилятор.

ответ

2

Unless otherwise specified, all standard library objects that have been moved from are placed in a valid but unspecified state. Действительный означает, что он может быть безопасно разрушен (например, при разматывании штабеля). В вашем примере s не возвращается, но сохраняется в обещании, но если он был возвращен обычным способом, то return s; компилятор мог неявно позвонить return move(s);.

+0

Я думал, что 'move' означает« кражу памяти », поэтому нет необходимости копировать? Является ли это специфической реализацией STL? – athos

+1

'move' скорее означает« украсть ячейку памяти, если она полезна или что угодно, но оставить этот объект в правильном состоянии ». После перемещения строки внутренний указатель данных может быть нулевым, и это допустимо, если деструктор не пытается освободить нулевой указатель. –

2

Это не проблема.

Перемещение семантики перемещает внутреннее значение переменной, а не самой переменной. Таким образом, у вас все еще есть отдельная строка назначения в исходной строке.

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

Он по-прежнему является действительным объектом (неизвестного значения) и будет надлежащим образом уничтожен при распаке стека.

+0

Я думал, что 'move' означает« кражу памяти », поэтому не нужно копировать? – athos

+1

@athos Well * move * - это кража внутреннего значения, которое может или не может совпадать с местом памяти. Со стороны, однако, он просто выглядит (и ведет себя) как копия, за исключением объекта, который был перемещен из (возможно) изменил его значение. – Galik

 Смежные вопросы

  • Нет связанных вопросов^_^