我想学习C ++,我有一点问题。我有一些Foo类的实例。我有一个vector<Foo> data
的FooContainer和一个方法
void FooContainer::add(Foo item) {
this->data.push_back(item)
}
我希望FooContainer成为Foo元素的真正拥护者。我不明白将项目从main传递到Foo的更好方法是什么。
我的主要内容是:
Foo item(...);
container.add(item);
通过这种方式,我在main中分配了一个对象,并将副本传递给容器。我将元素存在于2个位置,因此我必须在所有add()
之后删除主要元素。
或者最好在main中有一个指针,用new
关键字构造项目,并传递指针?这样,Container.data应该是vector<Foo*>
?
或者,再次将元素放在main中,通过引用添加到容器中,而不是在main中删除它?
我有点困惑。
出于教育目的,我不想使用c ++ 11或提升共享指针:我的想法在指针和引用以及基本的东西上混淆,然后进入高级参数(即使更优雅)我想要清楚我正在做的事情的基础!
答案 0 :(得分:3)
这一切都取决于你的需要。
如果您的所有实例都是Foo
[而不是Foo
的子类],则使用vector<Foo>
的IMO更简单,因此应该首选。
但是,如果您的某个类Bar
扩展为Foo
,那么尝试将其添加到vector
会导致object slicing,并且您的程序将表现不尽如人意。在这种情况下,您应该更喜欢vector<Foo*>
因此,在我开始时 - 这一切都取决于具体需求,但如果您计划扩展Foo
,则必须考虑最后一点。
答案 1 :(得分:2)
您可以将临时传递到容器中;这将在该行的末尾被销毁:
container.add(Foo(...));
在C ++ 11中,您可以直接将其构建到容器中:
template <typename Args...>
void FooContainer::emplace(Args && a) {
data.emplace_back(std::forward(a));
}
container.emplace(...);
(我的语法可能不太正确,因为我没有多使用可变参数模板)
在这两种情况下,请记住容器存储Foo
类型的对象。您不能存储子类型的对象;如果你尝试,只需复制基类部分就可以“切片”对象。如果你需要存储子类型(正如你的评论暗示的那样),那么你必须存储指针。
或者最好在main中有一个指针,使用new关键字构造项目,并传递指针?
这会在从容器中删除对象时产生记住删除对象的复杂性。您可以在C ++ 11中使用vector<unique_ptr<Foo>>
,或在C ++ 03中使用boost::ptr_vector<Foo>
来处理这个问题。这样做的好处是,您还可以在容器中存储Foo
的子类型对象,如果这是您可能想要做的事情。
或者,再次将元素放在main中,通过引用添加到容器中,而不是在main中删除它?
您不能将引用放在容器中。你可以在容器中放置指向局部变量的指针,如果非常小心它们在使用时不会被破坏(这很简单,如果所有内容都在main
内)。同样,这允许您存储Foo
的子类型,而不仅仅是Foo
本身。
答案 2 :(得分:2)
我发现boost :: ptr_vector非常适用于显式所有权语义。
我这样使用它(注意我使用VC9因此我使用std::auto_ptr
而不是改进的std::unique_ptr
):
//use unique_ptr instead if they are supported on your compiler
std::auto_ptr<MyClass> a( new MyClass("a") );
boost::ptr_vector<MyClass> owning_vector;
owning_vector.push_back(a);
// auto_ptr a is now invalid and the ownership of the object is
// solely with owning_vector
因此它可以解决您创建2个对象的问题,并且还可以清楚谁拥有新对象。 同样在语义方面,来自boost的API指针容器系列具有比原始指针(IMO)矢量更自然的sytax。
答案 3 :(得分:0)
我认为这不仅仅是所有权问题,而是仅仅是开销问题。
如果每次向对象添加对象时都有vector<foo>
,则将值复制到向量。
因此,除了创建要添加到矢量的临时对象,然后删除之外,您还在向量中创建另一个对象,并在那里复制值。
因此,最好只创建一个vector<foo*>
来保存对象。
或者更好地使用shared_ptr<foo>
和vector<shared_ptr<foo>>