функтор с ++ 11 в потоке - PullRequest
       27

функтор с ++ 11 в потоке

4 голосов
/ 25 января 2012

Пожалуйста, обратите внимание на следующий фрагмент кода.При использовании GCC 4.6.1 x становится 0, а y становится 1.

Почему я получаю разные результаты с использованием и без использования отдельного потока?Как изменить код так, чтобы обе версии давали одинаковый результат (т. Е. Целочисленное значение увеличивается на 1?)

Спасибо.

struct functor{
    void operator()(int & x){
        ++x;
    }    
};

void tfunc(functor & f, int & x){
    f(x);
}

int main(){
    functor f;
    int x = 0, y = 0;
    std::thread t = std::thread(tfunc, f, x);
    t.join();
    std::cout << "with thread " << x << std::endl;    
    f(y);
    std::cout << "without thread " << y << std::endl;
}

Ответы [ 2 ]

2 голосов
/ 25 января 2012

Легко увидеть, что происходит. Просто замените int на некопируемый тип (один с закрытым конструктором копирования), и компилятор укажет вам точное место, где libstdc++ пытается скопировать аргумент вместо использования ссылки. В моем случае это строка 138 в стандартном заголовке <tuple>.

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

ОБНОВЛЕНИЕ Стандарт гласит, что каждый аргумент std::thread::thread должен удовлетворять требованию MoveConstructible, и что фактические аргументы, передаваемые в функцию потока, создаются с помощью аргументов std::thread::thread. Это означает, что

  1. функция потока получает копии аргументов, а
  2. оригиналы вполне могут быть уничтожены в процессе.

Так что передача материала по ссылке не будет работать.

0 голосов
/ 13 августа 2014

Похоже, когда вызывается std::thread(tfunc, f, x), копируется x, и ссылка на временное значение передается в функтор, поэтому вызов функтора не изменит значение x. Я думаю, что в общем алгоритмы / функции STL всегда копируют аргументы. Если вы хотите, чтобы ваш вызов функтора изменил x, вы можете рассмотреть возможность использования указателя, так как даже если указатель скопирован, копия все еще указывает на тот же адрес.

...