用构造函数调用填充向量

Fill vector with constructor call

我有两个 classes,一个派生自另一个。我想分配一个 std:vector,它是派生 class 的填充。棘手的问题是我想让它调用写在基础 class.

中的移动构造函数

代码如下:

class Base{
    public:
    size_t size;
    double* buff;

    Base(size_t _size):size(_size){
        buff = new double[size];
    }

    Base() = delete;
    Base operator=(const Base&) = delete;
    Base(const Base&) = delete;

    Base(Base&& b):size(b.size), buff(b.buff){
        b.buff = nullptr;
    }
    Base operator=(Base&& b){
        size = b.size;
        buff = b.buff;
        b.buff = nullptr;
    }
};

class Derive : public Base{
    public:
    Derive(size_t _size):Base(_size){};
    Derive() = delete;
    Derive operator=(const Derive&) = delete;
    Derive(const Derive&) = delete;

    Derive(Derive&& b):Base(move(b)){}
    Derive operator=(Derive&& b){
        Base::operator=(move(b));
    }
};

/********/

vector<Derive> v(10, move(Derive(5)));

g++ 告诉我

error: use of deleted function ‘Derive::Derive(const Derive&)’
 { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

而且我不明白我应该做什么。

这里的问题是 std::vector(count, object) 复制 object, count 次,进入向量。您不能从它移动,因为您只能将一个对象移动到一个对象中。

如果您的 class 不可复制,那么您将无法使用它。但是你可以使用

std::vector<Type> foo;
foo.reserve(count);
for (int i = 0; i < count; ++i)
    foo.emplace_back(Types_parmeters);

您正在尝试从单一来源构建包含 10 个元素的向量。这是不可能的,因为一旦源元素被移动一次,它就会处于未确定状态。

因此,此构造函数在草案 n4296 中指定用于 C++14 以使用复制构造函数(强调我的):

23.3.6.2 vector constructors, copy, and assignment [vector.cons]
...
vector(size_type n, const T& value, const Allocator& = Allocator());
Effects: Constructs a vector with n copies of value, using the specified allocator.
Requires: T shall be CopyInsertable into *this. ...

另一种解决方案是编写您自己的 fill_n 版本来处理此用例。典型的 fill_n 确实复制了与向量构造函数相同的内容,但我们可以编写更现代的样式。

template <class T, class OutputIt, class Size, class .. Args>
OutputIt emplace_fill_n(OutputIt first, Size count, const Args& ... args)
{
    for (Size i = 0; i != count; ++i) {
        *first = T(args...);
        ++first;
    }
}

用法:

vector<Derive> v();
v.reserve(10);
emplace_fill_n<Derive>(back_inserter(v), 10);