拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 为什么for回圈和硬编码会产生不同的结果?

为什么for回圈和硬编码会产生不同的结果?

白鹭 - 2022-03-01 2110 0 0

我在 C 中创建了一个程序,当执行绪矢量的组件使用 for 回圈创建时不起作用,并且在创建硬编码时起作用。这是硬编码示例:

std::vector<std::thread> ThreadVector;
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[0], 0);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[1],1);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[2],2);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[3],3);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[4],4);})));

for(auto& t:ThreadVector)
        t.join();

maxLast是一个整数,它是双字符阵列的值。vals变量是一个特里普尔char阵列,认为在载体内的字符串的矢量。最后一个值是要通过函式发送的数字。cl.run 函式基本上只需要一个字符阵列阵列,将 maxLast 变量写入档案,然后在下一行写入阵列中的下一个字符串。呼叫文件名,trying然后添加数字,然后.txt函式如下所示:

void dir::run(int nums, char *vals[nums], int count){
    std::cout<<"got started "<<nums<<" "<<count<<std::endl;
    std::string filestr = "trying" std::to_string(count) ".txt";
    for(int i = 0; i < nums; i  ){
        writeLine(std::to_string(nums), filestr);
        writeLine(std::string(vals[i]), filestr);
    }
}

void dir::writeLine(std::string w, std::string p){
    FILE* stream = fopen(p.c_str(), "a ");  
    fputs(w.c_str(), stream);
    fputs("\n", stream);
    fclose(stream);

}

ThreadVector运行如上所示的硬编码到变量中时,它运行良好。但是,如果我按照以下方式运行它,将会有一个名为的档案trying5.txt,也会有我从未放入打印到档案上的字符阵列中的字符串。也会有一些执行绪收到相同的i值。

int i;
int ques=5;
for(i = 0; i < ques; i  ){
    printf("running %d\n", i);
    ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[i],i);})));
}
for(auto& t:ThreadVector)
        t.join();

它打印到终端的运行之一上(清理了一下):

running 0
running 1
running 2
running 3
running 4
got started 30 2
got started 30 2
got started 30 4
got started 30 3
got started 30 4

这显然不是应该发生的事情,正如前面提到的,有时终端会打印got started 30 5,我最终会得到一个名为trying5.txt. 我也试过push_back代替emplace_back.

uj5u.com热心网友回复:

std::thread([&]

[&]意味着闭包捕获所有物件都被参考捕获

cl.run(maxLast, vals[i],i)

i被参考捕获。i是父执行执行绪的回圈变量,它在回圈的每次迭代中递增。

除非发生显式同步,否则 C 无法保证每个执行执行绪何时执行与父执行执行绪中的任何内容相关的任何内容

这里没有发生这种同步。i在新的执行执行绪评估 thisval[i]以及i函式呼叫的离散自变量时,父执行执行绪可能已经增加它已经结束了回圈的当前迭代并移动到下一个回圈。甚至多次迭代。或者回圈可能在父执行执行绪中完全结束,i现在处于其最终值。

got started 30 2
got started 30 2
got started 30 4
got started 30 3
got started 30 4

你可以在这里看到这个结果。每个执行执行绪i在父执行执行绪迭代和增加i不可预测的次数后开始对其进行评估一些新的执行执行绪甚至设法同时进行评估i,导致 的观察值相同i

这就是“通过参考方式”捕获物件的方法。用于按值[=]捕获这意味着每个执行执行绪在创建执行执行绪时看到每个捕获物件的值。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *