在审查一个大型软件项目时,我提出了两种基本相同的方法,在std :: vector上推送初始条目
考虑像Foo这样的类
class Foo
{
public:
Foo(int param){
m_param = param;
}
setParam(int param){
m_param = param;
}
private:
int m_param;
}
考虑到任何适用的指标......速度,稳定性等,是否存在以下优选方法
Foo bar;
int val = 5;
bar.setParam(val);
std::vector<Foo> fooVec(1, bar);
对战
int val = 5;
std::vector<Foo> fooVec;
fooVec.push_back(Foo(val));
答案 0 :(得分:2)
考虑到任何适用的指标......速度,稳定性等,是否存在以下优选方法
可以认为 毫无疑问这种风格很差:
auto test1()
{
Foo bar; // redundant default construction
int val = 5; // redundant load
bar.setParam(val); // only now setting the value
std::vector<Foo> fooVec(1, bar); // redundant copy
return fooVec;
}
这是好风格:
auto test2()
{
return std::vector<Foo>(1, Foo(5));
}
性能怎么样,我们都关心这个,对吧?
但它在现实中意味着什么?一旦你启用了优化?...
__Z5test1v: ## @_Z5test1v
.cfi_startproc
## BB#0: ## %_ZNSt3__16vectorI3FooNS_9allocatorIS1_EEEC2EmRKS1_.exit1
pushq %rbx
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbx, -16
movq %rdi, %rbx
movq $0, 16(%rbx)
movq $0, 8(%rbx)
movq $0, (%rbx)
movl $4, %edi
callq __Znwm
movq %rax, (%rbx)
leaq 4(%rax), %rcx
movq %rcx, 16(%rbx)
movl $5, (%rax)
movq %rcx, 8(%rbx)
movq %rbx, %rax
popq %rbx
retq
.cfi_endproc
.globl __Z5test2v
.align 4, 0x90
__Z5test2v: ## @_Z5test2v
.cfi_startproc
## BB#0: ## %_ZNSt3__16vectorI3FooNS_9allocatorIS1_EEEC2EmRKS1_.exit1
pushq %rbx
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
.cfi_offset %rbx, -16
movq %rdi, %rbx
movq $0, 16(%rbx)
movq $0, 8(%rbx)
movq $0, (%rbx)
movl $4, %edi
callq __Znwm
movq %rax, (%rbx)
leaq 4(%rax), %rcx
movq %rcx, 16(%rbx)
movl $5, (%rax)
movq %rcx, 8(%rbx)
movq %rbx, %rax
popq %rbx
retq
.cfi_endproc
绝对没有任何区别。在这种情况下,生成的机器代码完全相同。
答案 1 :(得分:-1)
除非你有一个相当具体的理由使用其中一个,比如需要支持旧的(pre-C ++ 11)编译器,我只是使用:
std::vector<Foo> fooVec { 5 }; // or fooVec { foo(5) };, if you really prefer
这几乎可以保证与其他任何一个一样快速,稳定等等(并且可能更快,取决于......)