【问题标题】:c++ array indexing with non-const value [duplicate]具有非常量值的c ++数组索引[重复]
【发布时间】:2021-02-21 20:29:53
【问题描述】:

我有以下代码:

DisplayObject conveyor_belts[] = {eggs_1, eggs_2, flour_1, flour_2, sugar_1, sugar_2, butter_1, butter_2};
std::thread conveyor_belts_t[4];
for (int j = 0; j < 4; j++) {
    conveyor_belts_t[j] = std::thread([&](){
        conveyor_belts[j * 2].draw(15, 78 + i * 3);  // segmentation fault here
    });
}

我为 displayObject 定义了一个复制构造函数,但上面的代码在突出显示的行处给出了分段错误。我可以通过以下方式解决此问题:

DisplayObject conveyor_belts[] = {eggs_1, eggs_2, flour_1, flour_2, sugar_1, sugar_2, butter_1, butter_2};
std::thread conveyor_belts_t[4];
for (int j = 0; j < 4; j++) {
    conveyor_belts_t[j] = std::thread([&](){
        conveyor_belts[0].draw(15, 78 + i * 3);
    });
}

我想知道为什么变量索引会给我分段错误

【问题讨论】:

  • 您通过reference自动捕获了循环变量j。这是不正确的。您必须在 lambda 的捕获列表中按值捕获 j。作为个人风格偏好,我从不使用自动捕捉。我更愿意明确说明我给 lambda 的确切内容。
  • @paddy 谢谢,这行得通!你能详细说明为什么我不能通过引用捕获 j 吗?
  • 因为它会改变然后被销毁,而你的线程都将尝试使用它。此外,这是不正确的。您希望每个线程都使用j 在创建线程时所具有的特定值。按价值捕获是做到这一点的方法。
  • 如果j 在您读取它时超出范围,您将有未定义的行为。如果你碰巧在它到达4 时读到它,你会得到4 * 2 并越界访问数组。同样,未定义的行为。

标签: c++ constants


【解决方案1】:

在你的执行线程中

conveyor_belts[j * 2].draw(15, 78 + i * 3);

C++ 不保证新的执行线程将执行此代码并读取值j,该值通过引用捕获 在原始执行线程迭代之前for 循环 并增加此处引用的j 的值。 C++ 向您保证的是,新的执行线程std::thread 构造后的某个时间点开始执行。这是您唯一的保证。

很有可能,当所有执行线程唤醒 for 循环时,循环已经完成了迭代,所有四个执行线程都在愉快地查看它们捕获的对 j 的引用,该引用现已达到其最终值4 的值,所有四个执行线程都会很乐意使用 j 的值,现在是 4,因为它是通过引用捕获的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-08
    • 1970-01-01
    • 2019-07-10
    • 2012-03-06
    • 2010-10-28
    • 2019-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多