[英]std::vector::emplace_back with lvalue expression
Does it ever make practical sense to use emplace_back
with lvalue of some struct S
: 将
emplace_back
与某些struct S
左值一起使用是否真的有意义:
like this: 像这样:
std::vector<S> v;
auto s = S(/*...*/);
v.emplace_back(s);
Instead of just: 而不仅仅是:
v.emplace_back(/* S constructor arguments */);
or is it just plain misuse of emplace_back
, that only happen to work because const S&
(and thus a copy constructor) is legitimate instantiation for Args... args
inside emplace_back
, and it is not forbidden explicitely? 或者它只是简单地滥用
emplace_back
,只是因为const S&
(以及复制构造函数)是emplace_back
Args... args
合法实例,并且它不是明确禁止的吗?
As you already said, passing const S&
would just invoke the copy constructor. 正如您已经说过的,传递
const S&
只会调用复制构造函数。
Unless you intend to use s
in some way before passing it to emplace_back
, it is therefore not necessarily wise. 除非你打算在将它传递给
emplace_back
之前以某种方式使用s
,否则它不一定是明智的。
However, if the code to create s
was, for instance, exceptionally long, it could improve readability to put it and the code for emplace_back
on separate lines. 但是,如果创建
s
的代码特别长,它可以提高将它和emplace_back
的代码放在不同行上的可读性。 Compilers are extremely good at optimizing such cases and will probably generate the same code anyways (if the copy constructor is default). 编译器非常擅长优化这种情况,并且可能会生成相同的代码(如果复制构造函数是默认的)。 Basic example: https://godbolt.org/z/D1FClE
基本示例: https : //godbolt.org/z/D1FClE
If it improves readability or maintainability do it, otherwise there's no value in it. 如果它提高了可读性或可维护性,那么它就没有价值。
If s
is not needed later in the code, then it is a misuse of the emplace_back()
function. 如果稍后在代码中不需要
s
,那么它是对emplace_back()
函数的误用。 This is because you are invoking the copy constructor of the S
class instead of passing the arguments to the emplace_back()
which will use the correct constructor from S
. 这是因为您正在调用
S
类的复制构造函数,而不是将参数传递给emplace_back()
,后者将使用S
的正确构造函数。
Consider the following code: 请考虑以下代码:
#include <iostream>
#include <vector>
struct S
{
S() {std::cout<< " default ctor" <<std::endl;}
S(int) {std::cout<< " user-def ctor" <<std::endl;}
S(const S &) {std::cout<< " copy ctor" <<std::endl;}
S(S &&) {std::cout<< " move ctor" <<std::endl;}
};
int main()
{
std::vector<S> v;
v.reserve(5);
std::cout<< "auto calls: " <<std::endl;
auto s = S();
std::cout<<std::endl;
std::cout<< "emplace_back( s ) calls: " <<std::endl;
v.emplace_back(s);
std::cout<<std::endl;
std::cout<< "emplace_back( std::move(s) ) calls: " <<std::endl;
v.emplace_back(std::move(s));
std::cout<<std::endl;
std::cout<< "emplace_back( S{} ) calls: " <<std::endl;
v.emplace_back(S{});
std::cout<<std::endl;
std::cout<< "emplace_back( ) calls: " <<std::endl;
v.emplace_back();
std::cout<<std::endl;
std::cout<< "emplace_back( 2 ) calls: " <<std::endl;
v.emplace_back(2);
std::cout<<std::endl;
}
The results are: 结果是:
auto calls:
default ctor
emplace_back( s ) calls:
copy ctor
emplace_back( std::move(s) ) calls:
move ctor
emplace_back( S{} ) calls:
default ctor
move ctor
emplace_back( ) calls:
default ctor
emplace_back( 2 ) calls:
user-def ctor
The reserve is used to allocate space for 5 S
s. 储备用于为5分配空间
S
秒。 Without reserving the space, the outputs would include additional calls to the copy ctors from the vector. 如果不保留空间,输出将包括从向量中复制ctors的附加调用。
When you just pass the arguments to the constructor of S
(in this case, nothing), the emplace_back()
creates an S object using the default ctor directly inside the vector. 当你只是将参数传递给
S
的构造函数(在这种情况下,没有)时, emplace_back()
使用直接在向量内部的默认ctor创建一个S对象。
Btw, see the example in godbolt which is your friend in these cases to see exactly what happens in the background. 顺便说一下,看看godbolt中的例子,在这些情况下,你的朋友可以看到背景中发生了什么。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.