mar*_*ack 10 c++ overhead static-cast
我有一个结构模板,它采用两种类型(T
和S
),并在某些时候使用a static_cast
从一种类型转换为另一种类型.它往往是那么回事T
,并S
属于同一类型.
设置的简化示例:
template <typename T, typename S = T>
struct foo
{
void bar(T val)
{
/* ... */
some_other_function(static_cast<S>(val));
/* ... */
}
};
Run Code Online (Sandbox Code Playgroud)
在S
与类相同的情况下,是否T
可以static_cast
引入额外的开销,或者它是否总是被忽略的空操作?
如果它确实引入了开销,是否有一个简单的模板元编程技巧,static_cast
只在需要时执行,或者我是否需要创建部分特化以应对T == S
案例?foo
如果可能的话,我宁愿避免整个模板的部分特化.
是的,它可以.
这是一个例子:
struct A {
A( A const& ) {
std::cout << "expensive copy\n";
}
};
template<typename T>
void noop( T const& ) {}
template <typename T, typename S = T>
void bar(T val)
{
noop(static_cast<S>(val));
}
template <typename T>
void bar2(T val)
{
noop(val);
}
int main() {
std::cout << "start\n";
A a;
std::cout << "bar2\n";
bar2(a); // one expensive copy
std::cout << "bar\n";
bar(a); // two expensive copies
std::cout << "done";
}
Run Code Online (Sandbox Code Playgroud)
基本上,a static_cast
可以导致调用复制构造函数.
对于某些类型(如int
),复制构造函数基本上是免费的,编译器可以消除它.
对于其他类型,它不能.在这种情况下,复制省略也是不合法的:如果您的复制构造函数有副作用,或者编译器无法证明它没有副作用(如果复制构造函数不重要则通用),它将被调用.
为了补充Yakk 的回答,我决定发布一些程序集来确认这一点。我已经用作std::string
测试类型。
foo<std::string>.bar()
- 没有铸造
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movq %rcx, 16(%rbp)
movq %rdx, 24(%rbp)
movq 24(%rbp), %rax
movq %rax, %rcx
call _Z19some_other_functionRKSs
nop
addq $32, %rsp
popq %rbp
ret
Run Code Online (Sandbox Code Playgroud)
foo<std::string>.bar()
—— static_cast<T>()
pushq %rbp
pushq %rbx
subq $56, %rsp
leaq 128(%rsp), %rbp
movq %rcx, -48(%rbp)
movq %rdx, -40(%rbp)
movq -40(%rbp), %rdx
leaq -96(%rbp), %rax
movq %rax, %rcx
call _ZNSsC1ERKSs // std::string.string()
leaq -96(%rbp), %rax
movq %rax, %rcx
call _Z19some_other_functionRKSs
leaq -96(%rbp), %rax
movq %rax, %rcx
call _ZNSsD1Ev // std::string.~string()
jmp .L12
movq %rax, %rbx
leaq -96(%rbp), %rax
movq %rax, %rcx
call _ZNSsD1Ev // std::string.~string()
movq %rbx, %rax
movq %rax, %rcx
call _Unwind_Resume
nop
.L12:
addq $56, %rsp
popq %rbx
popq %rbp
ret
Run Code Online (Sandbox Code Playgroud)
此代码仅使用-O0
. 任何优化级别都会平衡这两种情况。