C++ OpenMP 对象计数器使用对象的 std::vector 进行不正确的计数

C++ OpenMP object counter incorrect counts with std::vector of objects

本文关键字:对象 不正确 vector std OpenMP 计数器 C++      更新时间:2023-10-16

我需要一个线程安全计数器来记录当前类型为 Apple 的对象数。 我试图用 OpenMP 制作一个简单的,但我不明白为什么计数不正确。 以下是该类的简化,包含实际测试代码和实际输出:

class Apple {
public:
    Apple();
    ~Apple();
    static int getThreadCount();
private:
    static int threadCount;
    void threadCountIncrease();
    void threadCountDecrease();
};
Apple::Apple() {
    threadCountIncrease();
}
Apple::~Apple() {
    threadCountDecrease();
}
void Apple::threadCountIncrease() {
    #pragma omp critical(AppleThreadCount)
    {
    std::cout << "## COUNT ++" << "n";
    ++threadCount;
    }
}
void Apple::threadCountDecrease() {
    #pragma omp critical(AppleThreadCount)
    {
    std::cout << "## COUNT --" << "n";
    --threadCount;
    }
}

测试代码

std::vector<Apple> apples;
cout << Apple::getThreadCount() << "n";
for(int i=0; i<3; ++i) {
    apples.push_back(Apple());
    cout << Apple::getThreadCount() << "n";
}

我不明白的输出

## COUNT ++
## COUNT --
0
## COUNT ++
## COUNT --
## COUNT --
-1
## COUNT ++
## COUNT --
## COUNT --
## COUNT --
-3
## COUNT --
## COUNT --
## COUNT --

为什么"COUNT --"出现次数多于"COUNT ++"次数? 为什么最后显示的计数是 -3 而不是 3?


多亏了公认的答案,我最终放弃了我正在做的事情,转而支持这个解决方案。

我首先要指出的是,我的解释可能并不完全技术正确。

发生的一件事是,当您执行apples.push_back(Apple());时,将创建元素的副本。由于尚未定义复制构造函数,因此不会为此副本调用threadCountIncrease

因此,您最终将获得至少两倍于++ --.

除此之外,当std::vector大小增加时,还需要分配更多内存。根据实现的不同,这将导致重新分配或数据副本。在您的情况下,确实会出现额外的副本

当您在循环之前添加apples.reserve(10);时,您将看到--计数会减少,因为std::vector已经为至少 10 个元素保留了空间。