c++ - 有效地用初始值初始化 vector

标签 c++

给定此类型进行测试:

struct Counter
{
    static int count;

    Counter(int)
    {
        count++;
    }

    Counter(const Counter&)
    {
        count++;
    }

    Counter(Counter&&) noexcept
    {

    }
};

int Counter::count = 0;

假设我们有以下内容:

std::vector<Counter> vec(5, 0);

根据VS2015,创建了6个Counter对象。我知道只有 5 个永久对象。为什么编译器不从构造函数参数中放置对象,或者将临时对象移动到第一个位置,然后从中复制其余的对象?

即使 vector 的初始大小设置为 0,仍然会创建 1 个对象。

std::vector<Counter> vec(0, 0);

如果大小直到运行时才知道并且通常为 0(无操作)并且容器中的类型复制或构造成本高昂,那么这一点可能很重要。

在一条语句中初始化 vector 通常很方便,特别是当它们是初始化列表中的类成员或常量时。我怎样才能像下面的代码一样有效地做到这一点:

std::vector<Counter> vec;
vec.reserve(size);
for (size_t i = 0; i < size; i++)
{
    vec.emplace_back(0);
}

它仅构造与 vector 中存储的对象一样多的包含对象。

最佳答案

您可以简单地定义一个函数,按照您想要的方式创建 vector 。

作为一个函数,初始化代码是异常安全的。

#include <iostream>
#include <vector>
#include <stddef.h>     // ptrdiff_t
#include <utility>      // std::forward
using namespace std;

struct Counter
{
    static int n_constructor_calls;

    Counter( int )
    {
        ++n_constructor_calls;
    }

    Counter( Counter const& )
    {
        ++n_constructor_calls;
    }

    Counter( Counter&& ) noexcept
    {
        ++n_constructor_calls;
    }
};

int Counter::n_constructor_calls = 0;

//--------------------------------------

using Size = ptrdiff_t;
using Index = Size;

template< class Item, class... Args >
auto make_vector( Size const n, Args&&... args )
    -> vector<Item>
{
    vector<Item>    result;
    result.reserve( n );
    for( Index i = 0; i < n; ++i )
    {
        result.emplace_back( forward<Args>( args )... );
    }
    return result;
}

auto main() -> int
{
    auto vec = make_vector<Counter>( 5, 42 );
    cout << Counter::n_constructor_calls << " constructor calls.\n";
}

(这输出“5 个构造函数调用。”)

您本质上会问,为什么没有定义 vector 构造函数来执行此操作,

Why doesn't the compiler emplace the objects from the constructor parameters, or move the temporary object into the first position and then copy the rest from it?

原因之一是该构造函数是在 C++11 中引入移动语义之前定义的。

相对于现有的非常庞大的 C++ 代码库而言,引入额外的构造函数(这会更改重载行为)或更改现有构造函数的行为的成本高昂。

关于c++ - 有效地用初始值初始化 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33335659/

相关文章:

c++ - 在 C++ 中划分后的奇怪结果

c++ - 现代 CMake (3.8+) - FindCUDA 已弃用,非 .cu 文件呢?

c++ - range-for 表达式中的临时生命周期

c++ - 我想创建一个函数,我可以在其中输入一个字符串,它会输出一个困惑版本的字符串

C++通过抽象基类在未知派生类上调用复制构造函数

c++ - 从数组打印时零不显示为 0

c++ - gmock.h 不包含在我的 Google 测试的外部依赖项中

C++继承/模板问题

c++ - 如何方便快捷的存储一个大词库?

c++ - 使用 C++ 读取 txt 文件并快速解析它们并 boost 内存映射文件