在现代C 不良实践中,原始指针的使用是



我想在没有对象切片的情况下保存基类实例的向量(这样我也可以存储基本子女的实例而无需任何问题),同时保持多态性行为而无需添加列表复制值,而是通过引用。

考虑以下源文件:

#include <iostream>
#include <string>
#include <vector>
#include <memory>
class Entity
{
public:
    Entity(){this->edited = false;}
    virtual std::string name() = 0;
    bool edited;
};
class Player: public Entity
{
public:
    Player(): Entity(){}
    std::string name(){return "player";}
};
int main()
{
    std::vector<Entity*> entities;
    Player p;
    entities.push_back(&p);
    entities.at(0)->edited = true;
    Entity* ent = entities.at(0);
    std::cout << "ent = " << ent->name() << ", edited = " << ent->edited << ".n";
    return 0;
}

我获得以下输出:

ent = player, edited = 1.

当输出显示(通过打印"播放器"并显示'编辑'的更改)时,由于原始指针而保持多态性行为,我能够无问题编辑列表的成员。

澄清我要的内容:我可以使用std :: Reference_wrapper实现完全相同的行为吗?当我尝试使用Reference_wrapper时,无法实现相同的行为,因为需要指针才能实现这种多态性行为?如果Reference_wrappers不是一个可行的替代方案,尽管我知道我添加到向量的播放器的实例是堆栈变量,但使用共享_ptr是明智的吗?在我的特定示例中,由于我希望对向量的成员共享所有权,因此我会赞成共享_ptr。有什么更好的方法可以实现这种行为?

非持有指针在现代C 中很好。但是,如果您的指针是拥有,则最好有一个很好的理由使用原始指针而不是智能指针。即使在最坏的情况下,您仍然应该能够编写自己的智能指针。您的示例是一个非拥有指针。

使用std::reference_wrapper<T>在这里不会为您带来任何收获。我包括了您的示例,已修改以使用它。请注意,直接操纵矢量中的元素有些烦人。

int main()
{
    std::vector<std::reference_wrapper<Entity>> entities;
    Player p;
    entities.push_back(p);
    entities.front().get().edited = true;
    Entity & ent = entities.front();
    std::cout << "ent = " << ent.name() << ", edited = " << ent.edited << ".n";
    return 0;
}

原始指针只是一种工具,就像C 提供的许多其他指针一样。当它是正确的工具时,不要害怕使用。现代C 带来的最重要的变化是,它已经消除了原始指针。经验法则是,如果您必须记住delete您做错了。

请注意,std::vector<T>::front()是获得第一个元素的首选方法,并且当您知道索引有效时,不建议使用std::vector::at

那里没有错。唯一可能是不好的情况是,当您开始分配实体对象并忘记删除它们时。

std::vector<Entity*> entities;
entities.push_back(new Player());
// Somthing that may throw exception
delete entities.at(0)

这有点不同的问题。

相关内容

  • 没有找到相关文章

最新更新