C++;:对象向量与指向新对象的指针向量? 我想通过编写一个示例软件渲染器来提高我的C++技能。它获取由三维空间中的点组成的对象,并将其映射到二维视口,并为视图中的每个点绘制大小不同的圆。哪一个更好: class World{ vector<ObjectBaseClass> object_list; public: void generate(){ object_list.clear(); object_list.push_back(DerivedClass1()); object_list.push_back(DerivedClass2()); 阶级世界{ 向量对象列表; 公众: void生成(){ object_list.clear(); 对象列表。向后推(DerivedClass1()); 对象列表。向后推(DerivedClass2());

C++;:对象向量与指向新对象的指针向量? 我想通过编写一个示例软件渲染器来提高我的C++技能。它获取由三维空间中的点组成的对象,并将其映射到二维视口,并为视图中的每个点绘制大小不同的圆。哪一个更好: class World{ vector<ObjectBaseClass> object_list; public: void generate(){ object_list.clear(); object_list.push_back(DerivedClass1()); object_list.push_back(DerivedClass2()); 阶级世界{ 向量对象列表; 公众: void生成(){ object_list.clear(); 对象列表。向后推(DerivedClass1()); 对象列表。向后推(DerivedClass2());,c++,pointers,vector,C++,Pointers,Vector,或者 阶级世界{ 向量对象列表; 公众: void生成(){ object_list.clear(); object_list.push_back(new DerivedClass1()); 对象列表。向后推(新的DerivedClass2()); ?如果在第二个示例中使用指针来创建新对象,那么就不能使用向量了,因为在第一个示例中,向量会自动调用DerivedClass析构函数,但在第二个示例中不会。使用向量时,指向新对象的指针是必要的,因为只要您使用它们的访问,它们就可以自己处理内存管理方法

或者

阶级世界{
向量对象列表;
公众:
void生成(){
object_list.clear();
object_list.push_back(new DerivedClass1());
对象列表。向后推(新的DerivedClass2());
?如果在第二个示例中使用指针来创建新对象,那么就不能使用向量了,因为在第一个示例中,向量会自动调用DerivedClass析构函数,但在第二个示例中不会。使用向量时,指向新对象的指针是必要的,因为只要您使用它们的访问,它们就可以自己处理内存管理方法?现在假设我有另一种方法:

void drawfrom(Viewport& view){
    for (unsigned int i=0;i<object_list.size();++i){
        object_list.at(i).draw(view);
    }
}
void drawfrom(视口和视图){

对于(unsigned int i=0;i对于您的第一个问题,通常倾向于使用自动分配的对象,而不是动态分配的对象(换句话说,不存储指针),只要对于所讨论的类型,复制构造和分配是可能的,并且不会非常昂贵

如果无法复制或分配对象,则无论如何都无法将其直接放入
std::vector
,因此问题没有意义。如果复制和/或分配操作成本高昂(例如,对象存储大量数据),则出于效率原因,您可能希望存储指针。否则,通常最好不要存储指针,原因与您提到的完全相同(自动释放)


至于第二个问题,是的,这是存储指针的另一个有效原因。动态分派(虚拟方法调用)仅对指针和引用有效(并且不能在
std::vector
中存储引用)。如果需要在同一个向量中存储多个多态类型的对象,则必须存储指针以避免切片。

使用此代码无法获得所需的内容

class World{
    vector<ObjectBaseClass> object_list;
public:
    void generate(){
        object_list.clear();
        object_list.push_back(DerivedClass1());
        object_list.push_back(DerivedClass2());
阶级世界{
向量对象列表;
公众:
void生成(){
object_list.clear();
对象列表。向后推(DerivedClass1());
对象列表。向后推(DerivedClass2());
将要发生的事情称为对象切片。您将得到ObjectBaseClass的向量


要使多态性发挥作用,您必须使用某种指针。boost或其他库中可能有一些智能指针或引用可供使用,使代码比第二个建议的解决方案更安全。

好吧,这取决于您试图对向量做什么


如果您不使用指针,那么它就是您传入的对象的一个副本,它会被放到向量上。如果它是一个简单的对象,并且/或者您不想费心跟踪它们的存储,这可能正是您想要的。如果它是复杂的,或者构造和销毁非常耗时,您可能更愿意这样做K只有一次,并把指针传递到向量中。

因为你明确地声明你想提高你的C++,我建议你开始使用。这可以帮助你用三种不同的方式解决问题:

使用
共享\u ptr
使用a可以像这样声明向量:

std::vector< boost::shared_ptr< ObjectBase > > object_list;
typedef std::vector< boost::shared_ptr< ObjectBase > >::iterator ObjectIterator;

for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
    (*it)->draw(view);
boost::ptr_vector< ObjectBase > object_list;
typedef boost::ptr_vector< ObjectBase >::iterator ObjectIterator;

for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
    (*it)->draw(view);
std::vector< boost::reference_wrapper< ObjectBase > > object_list;
typedef std::vector< boost::reference_wrapper< ObjectBase > >::iterator 
    ObjectIterator;

for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
    it->draw(view);
然后像这样使用它:

std::vector< boost::shared_ptr< ObjectBase > > object_list;
typedef std::vector< boost::shared_ptr< ObjectBase > >::iterator ObjectIterator;

for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
    (*it)->draw(view);
boost::ptr_vector< ObjectBase > object_list;
typedef boost::ptr_vector< ObjectBase >::iterator ObjectIterator;

for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
    (*it)->draw(view);
std::vector< boost::reference_wrapper< ObjectBase > > object_list;
typedef std::vector< boost::reference_wrapper< ObjectBase > >::iterator 
    ObjectIterator;

for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
    it->draw(view);
然后像这样使用它:

std::vector< boost::shared_ptr< ObjectBase > > object_list;
typedef std::vector< boost::shared_ptr< ObjectBase > >::iterator ObjectIterator;

for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
    (*it)->draw(view);
boost::ptr_vector< ObjectBase > object_list;
typedef boost::ptr_vector< ObjectBase >::iterator ObjectIterator;

for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
    (*it)->draw(view);
std::vector< boost::reference_wrapper< ObjectBase > > object_list;
typedef std::vector< boost::reference_wrapper< ObjectBase > >::iterator 
    ObjectIterator;

for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
    it->draw(view);
typedef std::vector>::迭代器
客观主义者;
for(ObjectIterator it=object_list.begin();it!=object_list.end();it++)
它->绘制(视图);
请注意,在上述方法中,您不必首先取消对迭代器的引用。但是,只有在对象的生存期在其他地方管理并且保证比
向量的生存期更长的情况下,这才有效

关于C++11的注意事项:
reference\u wrapper
也在C++11中进行了标准化,现在可以作为
std::reference\u wrapper
使用,无需Boost


正如s的回答中所指出的,您的第一种方法会导致。一般来说,在使用容器时,您可能需要仔细研究。

thnx编辑为不分散问题的注意力
shared\u ptr
vector
中的性能可能非常糟糕,具体取决于您执行的操作。出于通常目的,我建议
ptr_vector
。在您的ptr_vector示例中,首先使用“boost:ptr_vector”,然后在typedef中使用“std::ptr_vector”。我尝试编辑文章,但显然编辑长度必须至少为6个字符和“boost”只有5个字符。@bsegraves:谢谢,我已经修复了它。在上面的示例中,动态创建对象和自动分配对象之间是否存在时间差?哪种解决方案更适合优化?