【问题标题】:C++ vectors of classes with constructors带有构造函数的类的 C++ 向量
【发布时间】:2011-03-27 02:33:15
【问题描述】:
//Using g++ and ubuntu.
#include <vector>
using namespace std;

定义一个类:

class foo(){
(...)
foo(int arg1, double arg2);
}

构造函数:

foo::foo(int arg1, double arg2){ 
(...) //arrays whose length depend upon arg1 and arg2
} 

我想做这样的事情:

vector<foo> bar(10); //error: no matching function for call to 'foo::foo()'
bar[0] = new foo(123, 4.56);
(...)

另一种方法(我不太喜欢)是使用 push_back:

vector<foo> bar; //works
bar.push_back(new foo(123, 4.56)); //throws similar error.
//Omitting the "new" compiles but throws a "double free or corruption (fasttop)" on runtime.

我希望向量的不同元素构造不同,所以我不想使用“重复序列构造函数”。 应该怎么做?

【问题讨论】:

    标签: c++ class constructor vector


    【解决方案1】:

    当不需要创建动态内存时,为什么要使用new?当然使用new 会失败,当push_back 接受foo 时会导致foo*。 (毕竟,这就是你的向量。)

    push_back 有什么问题?如果要预先保留内存,请使用reserve();在vector 的构造函数中提供一个数字会生成第二个参数的许多副本(隐式为foo(),这将不起作用,因此会出现错误),这与简单地保留内存不同。

    如果操作正确(没有new)崩溃,则错误在于您的代码而不是向量。你可能还没有编写一个合适的类来管理资源。*(记住The Big Three,使用copy-and-swap idiom。)

    *我这样说是因为你说“//arrays whose length depend upon arg1 and arg2 ”,我怀疑这意味着你的班上有new[]。没有三巨头,你的资源管理就会失败。

    无论如何,你不应该管理资源,类有一个责任。这意味着它应该是动态数组,或者使用动态数组,但不能同时管理和使用动态数组。因此,将资源分解到他们自己的类中,然后创建另一个使用它们的类(你的)。动态数组是std::vector,所以你已经完成了。 任何时候如果您需要动态数组,请使用vector;没有理由不这样做。

    【讨论】:

    • +1 以获得非常好的答案。如果可以的话,我想给一个额外的 +1,因为不是说你应该总是使用 std::vector,而是你应该总是使用向量。
    【解决方案2】:

    std::vector 总是基于你没有在上面的 sn-p 中定义的默认构造函数创建元素。

    push_back 方法面临双重释放问题,因为您没有处理复制构造函数。

    【讨论】:

      【解决方案3】:
      vector<foo> bar(10); //error: no matching function for call to 'foo::foo()'
      

      这是失败的,因为您调用的 std::vector 构造函数是

      explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() );
      

      如您所见,它试图用 10 次调用不存在的 foo 的默认构造函数来填充向量。

      此外,所有带有new 的示例都将失败,因为向量需要foo 类型的对象,而不是foo *。此外,更改为vector&lt;foo *&gt; 也会失败,除非您在清除向量之前手动delete 每个成员。如果你真的想走动态内存分配路线,请创建一个vector&lt; shared_ptr&lt; foo &gt; &gt;shared_ptrBoost libraries 中可用,或者如果您的编译器包含 TR1 库,它将出现在 std::tr1 命名空间内的 &lt;memory&gt; 标头中,或者如果您的编译器具有 C++0x 库,它将在std 命名空间本身。

      你可能应该做的是:

      vector<foo> bar;
      bar.reserve(10);
      bar.push_back( foo( 1, 2 ) );
      ...
      ...
      bar.push_back( foo( 10, 20 ) ); //10 times
      

      【讨论】:

      • 可能应该提到 shared_ptr 是 boost 库或 C++0x 的一部分
      • @Kevin:我怀疑你应该使用std::vector,所以你不要。从使用中考虑资源,不要两者兼而有之。
      猜你喜欢
      • 2014-06-11
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 2011-08-22
      • 2015-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多