这是在现代C++糟糕实践中使用原始指针吗?

Har*_*and 6 c++ polymorphism smart-pointers stdvector c++11

我想要保存一个没有对象切片的Base类实例的向量(这样我也可以存储没有问题的Base的子实例),同时保持多态行为,而不是通过复制值而是通过引用添加到列表中.

请考虑以下源文件:

#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;
}
Run Code Online (Sandbox Code Playgroud)

我获得以下输出:

ent = player, edited = 1.
Run Code Online (Sandbox Code Playgroud)

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

澄清我在问什么:我可以使用std :: reference_wrapper来实现完全相同的行为吗?当我尝试使用reference_wrapper时,由于需要指针来实现这种多态行为,所以无法实现相同的行为?如果reference_wrappers不是一个可行的选择,虽然我完全知道我添加到向量中的Player实例是一个堆栈变量,但是使用shared_ptr是否明智?在我的特定示例中,我倾向于使用shared_ptr,因为我想要向量的成员共享所有权.有没有更好的方法来实现这种行为?

Fra*_*eux 5

在现代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;
}
Run Code Online (Sandbox Code Playgroud)

原始指针只是一种工具,就像c ++提供的许多其他工具一样.当它是正确的工具时,不要害怕使用它.现代c ++带来的最重大变化是它已经取消了拥有原始指针.经验法则是你必须记住delete你做错了.

请注意,这std::vector<T>::front()是获取第一个元素的首选方法,std::vector::at当您知道索引有效时,不鼓励使用.