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

Rom*_*dgz 3 c++ vector c++11

我试图将一些点保留到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;
}
Run Code Online (Sandbox Code Playgroud)

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

错误说:

在包含的文件中

/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
Run Code Online (Sandbox Code Playgroud)

'void std :: _ Construct(_T1*,_ Args && ...)的实例化[与_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*; 布尔

_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 = Foo; _Alloc = std :: allocator;

std :: vector <_Tp,_Alloc> :: pointer = Foo*; 的std ::矢量<_TP,

_Alloc> :: size_type = long unsigned 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 = Foo; _Alloc = std :: allocator; std :: vector <_Tp,_Alloc> :: size_type = long unsigned 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:
Run Code Online (Sandbox Code Playgroud)

注意:候选人是: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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Dav*_*eas 6

   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?
   }
Run Code Online (Sandbox Code Playgroud)

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

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

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


Luc*_*ore 5

改变

Foo(Foo &copyFoo) // bah!!! This can't make copies from temporaries
Run Code Online (Sandbox Code Playgroud)

Foo(const Foo &copyFoo)  // now that's one good-looking copy constructor
Run Code Online (Sandbox Code Playgroud)

  • 实际上,只需删除用户提供的复制构造函数即可。 (7认同)
  • 这并没有解决元素的 `reserve()` 空间问题,而是没有将它们添加到容器中,而只是访问缓冲区中的内存。 (2认同)