Как получить доступ к переменным в лямбда-функции?(C ++) - PullRequest
0 голосов
/ 31 января 2019

Я новичок в cpp, так что это может показаться тривиальным, но я хочу изменить локальную переменную (bool done1) в лямбда-функции, но похоже, что она ничего не делает с varialbe, и это все еще верно.Какие-либо предложения?Спасибо

    bool done1 = true;
    bool done2 = true;
    bool done3 = true;

    // associates each point to the nearest center
    std::thread thread_1([this](vector<Point> points,bool done) {
        for(int i = 0; i < total_points/3; i++) {
            int id_old_cluster = points[i].getCluster();
            int id_nearest_center = getIDNearestCenter(points[i]);
            if (id_old_cluster != id_nearest_center) {
                if (id_old_cluster != -1){
                    clusters[id_old_cluster].removePoint(points[i].getID());
                }
                points[i].setCluster(id_nearest_center);
                clusters[id_nearest_center].addPoint(points[i]);
                done = false;
            }
        }
    },points, done1);

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Если вы хотите изменить done1 в вашем потоке, лямбда должна брать bool по ссылке, а done1 должен быть заключен в reference_wrapper, когда вызывается ctor потока:

std::thread thread_1([this](vector<Point> points,bool& done) { // take by reference
    for(int i = 0; i < total_points/3; i++) {
        int id_old_cluster = points[i].getCluster();
        //...
            done = false;
        }
    }
},points, std::ref(done1) ); // <--- std::ref

Другой вариант - захватить done1 по ссылке, тогда лямбда принимает только один параметр:

[this,&done1](vector<Point> points) {
   //...
   done1 = true;
}, points);

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

std::thread thread_1([this](vector<Point>& points,bool& done) { // both args by ref
        for(int i = 0; i < total_points/3; i++) {
            int id_old_cluster = points[i].getCluster();
            //...
                done = false;
            }
        }
    }, std::ref(points), std::ref(done1) ); // <--- std::ref 2x
0 голосов
/ 31 января 2019

Вы не можете сделать это в части кода, которую вы только что представили.

Если вы попытаетесь захватить по ссылке, вы можете выйти из области видимости с вашей переменной.

InДля того чтобы этого не произошло, вам нужно будет добавить дополнительные thread_1.join() в той же области, что и bool done1 = true;

Но в этой ситуации ваше выполнение в другом потоке заблокирует ваш текущий поток.

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

event x;
bool a;
thread x([&a](){ a = true; x.set(); } );
x.wait();

См. https://docs.microsoft.com/en-us/cpp/parallel/concrt/reference/event-class?view=vs-2017

Еще одна вещь, которая может произойтиэто значение может быть кэшировано.Я бы рекомендовал использовать std :: atomic для совместного использования переменных в нескольких потоках.

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