安装调用移动构造函数的次数?



我是c++ 14的新手,我正在试验make_vector构建器,用于在一行中构建std::vector的元素,并在适当的位置。例如,构建器的用法如下:

make_vector<AnyStruct>() 
<< AnyStruct(1) 
<< AnyStruct(2) 
<< AnyStruct(3);
所以我创建了这个简单的生成器,如下所示:
template <typename T>
class make_vector final
{
public:
make_vector<T> &operator<<(T &&t)
{
std::cerr << "operator<< for T" << std::endl;
data_.emplace_back(std::forward<T>(t));
return *this;
}
operator std::vector<T> &&()
{
std::cerr << "implicitly convert to std::vector<T>" << std::endl;
return std::move(data_);
}
private:
std::vector<T> data_;
};
然后为构建器提供一个简单的结构体:
struct Foo
{
inline static size_t constructCount = 0;
inline static size_t moveCount = 0;
explicit Foo(int d) : data(d)
{
std::cerr << "Foo(int)" << std::endl;
++Foo::constructCount;
}
explicit Foo(Foo &&other) : data(other.data)
{
std::cerr << "Foo(Foo&&)" << std::endl;
++Foo::moveCount;
}
explicit Foo(const Foo &other) = delete;
const int data;
friend std::ostream &operator<<(std::ostream &os, const Foo &self)
{
os << "Foo(" << self.data << ")";
return os;
}
};

最后,我用以下代码测试我的make_vector:

int main(...) {
make_vector<Foo>() << Foo(1) << Foo(2) << Foo(3);
}

我看到非常奇怪的日志:

Foo(int) // 1st Foo(1)
operator<< for T
Foo(Foo&&)
Foo(int) // 2nd Foo(2)
operator<< for T
Foo(Foo&&)
Foo(Foo&&)
Foo(int) // 3rd Foo(3)
operator<< for T
Foo(Foo&&)
Foo(Foo&&)
Foo(Foo&&)

看起来第二个<< Foo(2)移动了两次,第三个<< Foo(3)移动了3次。这并不像我期望的那样,move- actor应该为每个Foo(...)发生一次。

我期望理想的日志是这样的:

Foo(int) // 1st Foo(1)
operator<< for T
Foo(Foo&&)
Foo(int) // 2nd Foo(2)
operator<< for T
Foo(Foo&&)
Foo(int) // 3rd Foo(3)
operator<< for T
Foo(Foo&&)

为什么多次调用move- actor ?

data_.emplace_back(std::forward<T>(t));

将向vector中添加元素。但是,如果vector用完空间,它将分配更大的内存块并复制或(如果可能的话)将现有对象移动到新的存储空间中。

你需要更聪明地缓存所有的对象,为它们保留足够的空间,并且只在最后放置它们。

最新更新