gcc是否有std::vector::emplace_back的扩展重载?

tuwxkamq  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(185)

根据cppreferencestd::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 );

这在文档中没有提到。是我遗漏了什么还是这只是一个编译器扩展?

nfeuvbwi

nfeuvbwi1#

foos.emplace_back(foo); // weird

这确实很奇怪!你请求emplace_back,这意味着你在调用构造函数,并且你把foo传递给构造函数。因此,你在调用复制构造函数。push_back也会做同样的事情!
这是一个隐式定义的默认复制构造函数,请参见复制构造函数中的cppreference:
如果没有为类类型(结构、类或联合)提供用户定义的复制构造函数,编译器将始终将复制构造函数声明为其类的非显式内联公共成员。
你没有定义一个复制构造函数,所以编译器会按照C++的要求为你定义一个复制构造函数。你可以避免这样做,让你的编译失败:
第一个
注意,你是在从foo中移出之后使用它的,这多少是非法的(你在foo中抛出std::move意味着foo不再应该持有任何资源)。
如果你真的只想删除move构造函数,基本上是相同的语法:Foo(Foo&&) = delete; .

3pmvbmvn

3pmvbmvn2#

template< class... Args >
reference emplace_back( Args&&... args );

可以推导出类似于(使用Args = Foo&

reference emplace_back( Foo& && args[0] );

其折叠成

reference emplace_back( Foo& args[0] );

相关问题