提问者:小点点

std::VectorObject>reserve方法是否需要对象类的复制构造函数?


我试着在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,

             from main.cpp:3: /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/stl_construct.h: In

void std::_construct(_t1*,_args&&...)的实例化[with_t1=

脚;_args=Foo':

/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)[with_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=fooo;_alloc=std::allocator;

std::vector<_tp,_alloc>::pointer=foo*;std::vector<_TP,

_ALLOC>::size_type=长无符号int'/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/vector.tcc:75:70:

“void std::vector<_tp,_alloc>::reserve(Std::vector<_tp,

_alloc>::size_type)[with_TP=foos;_alloc=std::allocator;std::vector<_TP,_alloc>::size_type=长无符号int'

main.cpp:31:24:此处必填

/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: note:   candidate expects 2 arguments, 1 provided main.cpp:17:5: note: Foo::Foo(Foo&)

 Foo(Foo &copyFoo){

 ^ main.cpp:17:5: note:   no known conversion for argument 1 from 'Foo' to 'Foo&' main.cpp:12:5: note: Foo::Foo()

 Foo(){

 ^ main.cpp:12:5: note:   candidate expects 0 arguments, 1 provided

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

编辑:我使用的是C++11。如果删除复制构造函数,则在reserve方法行收到以下错误:

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

这就是为什么我首先编写复制构造函数的原因。

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


共3个答案

匿名用户

   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?
   }

上面的代码是错误的。您正在访问容器中以外的元素。这样做的惯用方法是在容器上执行:

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

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

匿名用户

更改

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

Foo(const Foo &copyFoo)  // now that's one good-looking copy constructor

匿名用户

第一个问题是复制构造函数通过非常量引用获取参数,这会阻止从临时对象复制。

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

如果类非常复杂,需要一个非默认的复制构造函数,那么它应该

Foo(Foo const &);

注意,您不一定需要复制构造函数来将类型存储在

第二个问题是访问向量的未初始化元素。只为那么多元素保留内存,而不初始化它们;您需要先插入元素(使用或其他元素),然后才能访问它们。