根据cppreference,std::vector::emplace_back
只有一个签名,即:
template< class... Args >
reference emplace_back( Args&&... args );
在描述中,它说emplace_back
应该将它的每个参数转发给vector
中类型的构造函数。然而,当我使用gcc 12.2测试下面的代码时,它成功编译了:
#include <iostream>
#include <vector>
class Foo
{
public:
int x;
int y;
Foo(int x, int y) : x(x), y(y)
{}
};
int main()
{
std::vector<Foo> foos;
Foo foo(1, 2);
foos.push_back(std::move(foo));
foos.emplace_back(foo); // weird
}
(See在compiler explorer上)
我以为foos.emplace_back(foo);
这一行编译失败。看起来emplace_back
有这样的重载:
template< class T >
reference emplace_back( T& arg );
这在文档中没有提到。是我遗漏了什么还是这只是一个编译器扩展?
2条答案
按热度按时间nfeuvbwi1#
这确实很奇怪!你请求
emplace_back
,这意味着你在调用构造函数,并且你把foo
传递给构造函数。因此,你在调用复制构造函数。push_back
也会做同样的事情!这是一个隐式定义的默认复制构造函数,请参见复制构造函数中的cppreference:
如果没有为类类型(结构、类或联合)提供用户定义的复制构造函数,编译器将始终将复制构造函数声明为其类的非显式内联公共成员。
你没有定义一个复制构造函数,所以编译器会按照C++的要求为你定义一个复制构造函数。你可以避免这样做,让你的编译失败:
第一个
注意,你是在从
foo
中移出之后使用它的,这多少是非法的(你在foo
中抛出std::move
意味着foo
不再应该持有任何资源)。如果你真的只想删除move构造函数,基本上是相同的语法:
Foo(Foo&&) = delete;
.3pmvbmvn2#
可以推导出类似于(使用
Args = Foo&
)其折叠成