首页 文章

std :: vector <Object> reserve方法是否需要Object类的复制构造函数?

提问于
浏览
3

我试图在std :: vector中保留一些点,并且有一个我不明白的错误:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Foo{
public:    
    std::string str;
    int i;

    Foo(){
        this->str = "";
        this->i = 0;
    }

    Foo(Foo &copyFoo){
        this->str = copyFoo.str; //Or get methods if private members
        this->i = copyFoo.i;
    }

    Foo(std::string str, int i){
        this->str = str;
        this->i = i;
    }
};

int main()
{
   std::vector<Foo> fooVector;
   fooVector.reserve(20); // Error

   for(int i=0; i<20; i++){
       fooVector[i] = Foo("Test", i); // Or should I use operator new?
       // Or should I even stick to the push_back method?
   }

   return 0;
}

当然我可以不保留,它可能会工作 . 但现在我对它为什么现在不起作用感兴趣 . 我添加了复制构造函数,因为它看起来可能是我当时遇到的问题 . 但是在添加了复制构造函数之后,它也无法正常工作 .

错误说:

在/usr/local/gcc-4.8.1/include/c /4.8.1/vector:62:0中包含的文件中,来自main.cpp:3:/usr/local/gcc-4.8.1/include/ c /4.8.1/bits/stl_construct.h:在
实例化'void std :: _ Construct(T1 *, Args && ...)[与_T1 = Foo; _Args =]':/usr/local/gcc-4.8.1/include/c /4.8.1/bits/stl_uninitialized.h:75:53:从'static _ForwardIterator std :: __ uninitialized_copy <TrivialValueTypes>中需要: :_uninit_copy(_InputIterator,_InputIterator,_ForwardIterator)[with _InputIterator = std :: move_iterator; _ForwardIterator = Foo *; bool _TrivialValueTypes = false]'/usr/local/gcc-4.8.1/include/c /4.8.1/bits/stl_uninitialized.h:117:41:从'_ForwardIterator std :: uninitialized_copy(_InputIterator,_InputIterator,_ForwardIterator)中需要[使用_InputIterator = std :: move_iterator; _ForwardIterator = Foo *]'/usr/local/gcc-4.8.1/include/c /4.8.1/bits/stl_uninitialized.h:258:63:需要'_ForwardIterator std :: __ uninitialized_copy_a(_InputIterator,_InputIterator,_ForwardIterator, std :: allocator <_Tp>&)[with _InputIterator = std :: move_iterator; _ForwardIterator = Foo *; _Tp = Foo]'/usr/local/gcc-4.8.1/include/c /4.8.1/bits/stl_vector.h:1142:29:从'std :: vector <_Tp,_Alloc> :: pointer std中需要:: vector <_Tp,_Alloc> :: _ M_allocate_and_copy(std :: vector <_Tp,_Alloc> :: size_type,_ForwardIterator,_ForwardIterator)[with _ForwardIterator = std :: move_iterator; _Tp = Foo; _Alloc = std :: allocator; std :: vector <_Tp,_Alloc> :: pointer = Foo *; std :: vector <_Tp,_Alloc> :: size_type = long unsigned int]'/usr/local/gcc-4.8.1/include/c /4.8.1/bits/vector.tcc:75:70:required from' void std :: vector <_Tp,_Alloc> :: reserve(std :: vector <Tp,Alloc> :: size_type)[with _Tp = Foo; _Alloc = std :: allocator; std :: vector <_Tp,_Alloc> :: size_type = long unsigned int]'main.cpp:31:24:from here here /usr/local/gcc-4.8.1/include/c /4.8.1/bits/ stl_construct.h:75:7:错误:没有匹配函数来调用'Foo :: Foo(Foo)'{:: new(static_cast <void *>( p))T1(std :: forward <Args>( args) )...); }

^ /usr/local/gcc-4.8.1/include/c /4.8.1/bits/stl_construct.h:75:7:
注意:候选人是:main.cpp:22:5:注意:Foo :: Foo(std :: string,int)Foo(std :: string str,int i){

^ main.cpp:22:5:注意:候选人需要2个参数,1个提供main.cpp:17:5:注意:Foo :: Foo(Foo&)

Foo(Foo&copyFoo){

^ main.cpp:17:5:注意:参数1从'Foo'到'Foo&'main.cpp没有已知的转换:12:5:注意:Foo :: Foo()

美孚(){

^ main.cpp:12:5:注意:候选人需要0个参数,1提供

问题出在哪儿?我是否需要初始化std:vector对象,或者只是将每个位置分配给对象实例?

编辑:我正在使用C 11.如果我删除复制构造函数,我在保留方法行收到以下错误:

required from 'void std::_Construct(_T1*, _Args&& ---) [with _TI = Foo; _Args = {Foo&}]

这就是我首先编写复制构造函数的原因 .

我不想使用resize方法,因为我希望size方法返回包含在向量中的实际Foo对象数,而不是我保留的数量 .

4 回答

  • 0

    更改

    Foo(Foo &copyFoo) // bah!!! This can't make copies from temporaries
    

    Foo(const Foo &copyFoo)  // now that's one good-looking copy constructor
    
  • 1
    std::vector<Foo> fooVector;
       fooVector.reserve(20); // Error
    
       for(int i=0; i<20; i++){
           fooVector[i] = Foo("Test", i); // Or should I use operator new?
           // Or should I even stick to the push_back method?
       }
    

    上面的代码是错误的 . 您正在访问容器中 size() 之外的元素 . 这样做的惯用方法是在容器上做 push_back / emplace_back 来实际创建对象,而不仅仅是内存:

    for(int i=0; i<20; i++){
           fooVector.emplace_back("Test", i);  // Alternatively 'push_back'
       }
    

    除此之外,在C 11中,容器中使用的类型需要复制或移动构造函数 .

  • 6

    第一个问题是你的拷贝构造函数通过非const引用获取它的参数,这可以防止从临时值中复制 .

    在这种情况下,根本不需要声明复制构造函数:如果不这样做,那么将隐式定义一个复制每个成员,这就是你想要的 .

    如果类足够复杂,需要非默认的复制构造函数,那么它应该是

    Foo(Foo const &);
    

    请注意,您不一定需要复制构造函数来将类型存储在 vector 中;如果您不希望您的类可以复制,那么移动构造函数就足够了 .

    第二个问题是您正在访问向量的未初始化元素 . reserve 只是在没有初始化的情况下为这么多元素保留内存;您需要先插入元素(使用 resizeinsertpush_backemplace_back 或其他),然后才能访问它们 .

  • 4

    Luchian Grigorehis answer中所述,首先应修复复制构造函数 . 或者只是删除它,因为默认的一个就可以了 . 其次,要使用现在的代码,你应该使用resize代替reserve

    std::vector<Foo> fooVector;
    fooVector.resize(20);
    

    后者只保留内存,但容器的大小保持不变 - 在你的情况下 0 因此访问元素是非法的 . resize 另一方面做你想要的 .

    但总的来说,你甚至不应该这样做(例如here) . 只需在空向量上使用push_backemplace_back即可为其填充内容 . resize 将为您想要覆盖的每个元素调用默认构造函数 .

相关问题