C++ std::vector::emplace_back 不能用字符串值类编译

问题描述

/* Item.h */
struct Item {
    std::string name;

    Item(std::string _name) : name( std::move(_name) ) { }
};

/* main.cpp */
/* ... */
const int amount_of_items = val.size();
std::vector<Item> items(amount_of_items);

for( Json::Value::const_iterator itr = val.begin() ; itr != val.end() ; ++itr ) {
    items.emplace_back( "item_name" );
}

结果:

/usr/include/c++/8/bits/stl_construct.h:75:7: error: no matching function for call to ‘Item::Item()’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from main.cpp:8: Item.h:8:2: note: candidate: ‘Item::Item(std::__cxx11::string)’   Item(std::string _name) : name( std::move(_name) ) { }   ^~~~ Item.h:8:2: note:   candidate expects 1 argument,0 provided

我不知道为什么这不起作用 - 有什么想法吗?

解决方法

本声明:

std::vector<Item> items(amount_of_items);

需要 Item 的默认构造函数,因为您已要求编译器使用 amount_of_items 默认构造的 Item 填充数组。

相反,您需要简单地编写:

std::vector<Item> items;

因为 emplace_back 会根据需要增加数组。

请注意,如果您想预先为您的 items.reserve 预留空间,可以调用 Item

,

问题是您需要一个 Item 的默认构造函数用于此代码序列。默认构造函数被禁用,因为您有 Item 的自定义构造函数。

您可以通过添加 Item()=default; 来启用它。

除此之外,您还有一个逻辑错误:std::vector<Item> items(amount_of_items); 启动 itemsamount_of_items 的默认可构造元素。根据下一个序列,这不是您想要的,因为到最后,您的元素数量将翻倍。

你应该写

std::vector<Item> items;
items.reserve(amount_of_items);
,

您的结构中没有默认构造函数,因为您添加了非默认构造函数。您可以重新添加默认构造函数。

但错误行实际上是您的初始化(项目数量),这是尝试使用默认 c'tor 默认构造 item s。

所以我建议你添加一个默认的 c'tor:

    Item() = default;

或者用字符串初始化:

std::vector<Item> items(num_items,std::string(""));

此外,您的“移动”构造函数应该使用 r-value ref &&(并且可能也是显式的,因为它只有一个参数):

    Item() = default;

    //             here
    //               V
    explicit Item(std::string &&_name) : name( std::move(_name) ) { }
,

调用 std::vector 构造函数时:

std::vector<Item> items(amount_of_items);

所包含类型的默认构造函数:Item 被调用。您应该定义一个默认构造函数:

Item() = default

或者使用其他没有此要求的 std::vector 构造函数之一:

std::vector<Item> items(amount_of_items,{""});