C++核心静态成员变量指南

zdwk9cvp  于 11个月前  发布在  其他
关注(0)|答案(3)|浏览(163)

我在我的类中有一个私有的静态向量,它保存了一个指向所有从它创建的对象的指针。这是必要的,因为每个对象都需要访问所有其他对象的信息来执行一些计算:

// Header file:
class Example {
public:
    Example();
private:
    static std::vector<const Example*> examples_;
};
// Cpp file:
std::vector<const Example *> Example::examples_ = {};
Example::Example() {
    // intialization
    examples_.emplace_back(this);
}
void Example::DoCalc() {
    for (auto example : examples_) {
        // do stuff
    }
}

字符串
clang-tidy指出我违反了C++核心准则,即:“变量'examples_'是非常量且全局可访问的,请考虑将其设为常量(cppcoreguidelines-avoid-non-const-global-variables)”。
就我个人而言,我没有看到我的代码和核心准则中的示例代码之间的相似之处,特别是因为变量是在一个类中并且是私有的。实现这个功能的“正确”方法是什么?如果可以避免的话,我不想禁用clang-tidy的这种检查。

ux6nzvsh

ux6nzvsh1#

你所做的一切都很好。这就是class-static的真正目的。有些人会推荐替代方案,出于不相关的原因,这可能值得考虑.但不是因为clang-tidy在这里告诉你的任何事情。
你已经遇到了clang-tidy bug #48040。你可以看到这一点,因为它的消息传递是错误的:向量不是“全局可访问的”,至少在访问规则的意义上不是,因为它被标记为private(尽管它在翻译单元中全局存在,这很好)。
你的代码与引用的核心准则无关。

ohfgkhjo

ohfgkhjo2#

一个可能的解决方案是强制每个访问Example::examples_的客户端都要经过一个函数。然后将examples作为一个静态变量放入该函数中。这样,该对象将在第一次调用该函数时创建-与任何全局对象构造顺序无关。

// Header file:
class Example {
public:
    Example();
private:
    std::vector<const Example*>& examples();
};
// Cpp file:
std::vector<Example *>& Example::examples()
{
    static std::vector<Example *> examples_;
    return examples_;
};
Example::Example() {
    // intialization
    examples().emplace_back(this);
}
void Example::DoCalc() {
    for (auto example : examples()) {
        // do stuff
    }
}

字符串
当然,如果你确定你对全局对象没有问题,并且确定在Examples::examples_的构造过程中没有其他全局对象访问它,你可以忽略这个警告。这只是一个指导,你不需要严格遵守它。
正如Asteroids With Wings所指出的,准则I.2不适用于您的代码。但请注意,核心准则也打算禁止静态成员,请参阅To-do:Unclassified proto-rules:
避免静态类成员变量(竞争条件,几乎全局变量)

k4aesqcs

k4aesqcs3#

就我个人而言,我的代码与核心指导原则中的示例代码之间没有相似之处
你有一个变量,每个线程都可以访问,对Example的用户隐藏。与普通全局变量的唯一区别是它是private,也就是说,你不能在Example之外使用 nameExample::examples_引用它。

备注

规则是“避免”,而不是“不使用”。
实现此功能的“正确”方法可能是您如何拥有它,但我强烈建议您修改“每个对象需要访问所有其他对象的信息以执行某些计算”,以便将std::vector<const Example*>传递到需要它的地方,并跟踪所有相关的(特别是活动的)Example

替代:[...]另一种解决方案是将数据定义为某个对象的状态,将操作定义为成员函数。
**警告:**小心数据竞争:如果一个线程可以访问非本地数据(或通过引用传递的数据),而另一个线程执行被调用者,我们可以有一个数据竞争。每个指向可变数据的指针或引用都是一个潜在的数据竞争。

相关问题