std::vector::emplace_back 与左值表达式
std::vector::emplace_back with lvalue expression
使用带有某些结构S
的左值的emplace_back
是否具有实际意义:
喜欢这个:
std::vector<S> v;
auto s = S(/*...*/);
v.emplace_back(s);
而不仅仅是:
v.emplace_back(/* S constructor arguments */);
或者只是对emplace_back
的简单误用,只是因为const S&
(因此复制构造函数)是emplace_back
内部Args... args
的合法实例化,并且没有明确禁止?
正如你已经说过的,传递const S&
只会调用复制构造函数。
除非您打算在将s
传递给emplace_back
之前以某种方式使用它,否则它不一定是明智的。
但是,例如,如果用于创建s
的代码特别长,则可以提高可读性,将其和emplace_back
代码放在单独的行上。编译器非常擅长优化这种情况,并且无论如何都可能会生成相同的代码(如果复制构造函数是默认的)。基本示例:https://godbolt.org/z/D1FClE
如果它提高了可读性或可维护性,那就去做吧,否则就没有价值。
如果代码后面不需要s
,那么它是对emplace_back()
函数的误用。这是因为您正在调用S
类的复制构造函数,而不是将参数传递给将使用S
中的正确构造函数的emplace_back()
。
请考虑以下代码:
#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;
}
结果是:
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
储备用于分配5S
秒的空间。在不保留空间的情况下,输出将包括从向量对复制 ctors 的额外调用。
当您只是将参数传递给S
的构造函数(在本例中,什么都没有)时,emplace_back()
直接在向量内使用默认 ctor 创建一个 S 对象。
顺便说一句,请参阅Godbolt中的示例,在这些情况下,它是您的朋友,以确切地了解背景中发生的事情。
相关文章:
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中用vector填充一个简单的动态数组
- vector.resize()中的分配错误
- 使用std::vector的OpenCL矩阵乘法
- (C++)分析树以计算返回错误值的简单算术表达式
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 在某些循环内使用vector.push_back时出现分段错误
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 当vector是tje全局变量时,c++中vector的内存管理
- 提升精神:解析布尔表达式并简化为规范范式
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 使用 vector 检查表达式中的括号是否平衡
- 如何修复此错误:二进制表达式的操作数无效("std::vector<double>"和"double")?
- std::vector::emplace_back 与左值表达式
- 实现 vector 时二进制表达式的操作数无效
- 使用 std::vector 时抽象类类型"Shape"的新表达式无效错误
- std::vector pointer-表达式必须有类类型错误
- ublas:将ublas::vector包装为ublas:矩阵表达式
- 存储在vector中的表达式的延迟求值
- 运行时vector断言失败表达式:vector下标超出范围