C++ std::function和std::bind是否进行动态内存分配?
如果我这样做:-C++ std::function和std::bind是否进行动态内存分配?,c++,C++,如果我这样做:- class Thing { ... void function (const std::string& message); }; std::list<std::function<void()>> work; 调用std::bind或使用std::function是否会导致使用new或其他方式进行动态内存分配?或者所有存储都是在编译时分配的?如果标准没有说明什么,那在visual studio 2012中呢,因为我的程序只需
class Thing
{
...
void function (const std::string& message);
};
std::list<std::function<void()>> work;
调用std::bind或使用std::function是否会导致使用new或其他方式进行动态内存分配?或者所有存储都是在编译时分配的?如果标准没有说明什么,那在visual studio 2012中呢,因为我的程序只需要在此基础上构建,为了提高效率,我可能需要在考虑使用此机制的地方避免动态内存分配。标准没有规定,但通常很容易看出,
std::function
至少在某些情况下必须分配内存:
struct huge { char c[10000]; };
void foo(const huge &);
std::function<void()>{std::bind(foo, huge{})};
我对此不确定。我想,正如ecatmur所建议的,这取决于该平台的std实现。对于类似的问题,我已经从代码项目中成功地使用了这个实现。它支持许多平台。有很好的文档记录,没有动态内存分配 应避免在游戏或模拟中运行时进行通用动态内存分配。问题并不总是碎片或大瓶颈(这两个都是可以避免的有效原因),而是时间量通常是不确定的。在这里,更特定于域的内存分配策略,如“池”或“帧”将是有利的
我只是针对g++的情况做了一些研究 谈到std::function和动态内存分配,有两个关键点
#include <functional>
using namespace std;
class Thing
{
void foo();
void bar();
void function (const char * message);
};
char baz[1024];
void Thing::foo() {
new (baz) std::function<void()>(std::bind(&Thing::function, this, "Hello"));
}
void Thing::bar() {
const char * s = "Hello";
new (baz) std::function<void()>([this,s](){function(s);});
}
#包括
使用名称空间std;
阶级事务
{
void foo();
空心钢筋();
无效函数(常量字符*消息);
};
char-baz[1024];
void Thing::foo(){
新的(baz)std::function(std::bind(&Thing::function,这个“Hello”);
}
void Thing::bar(){
const char*s=“你好”;
新的(baz)std::function([this,s](){function(s);});
}
结果令人满意
Thing::foo():
mov r3, #0
push {r4, r5, r6, lr}
ldr r4, .L34
mov r6, r0
sub sp, sp, #16
mov r0, #16
str r3, [r4, #8]
bl operator new(unsigned int)
ldr r2, .L34+4
mov r1, #0
mov r3, r0
str r2, [sp]
mov r2, sp
ldr r5, .L34+8
ldr lr, .L34+12
ldr ip, .L34+16
str r1, [sp, #4]
str r6, [r0, #12]
str r0, [r4]
str r5, [r3, #8]
ldm r2, {r0, r1}
str lr, [r4, #12]
stm r3, {r0, r1}
str ip, [r4, #8]
add sp, sp, #16
pop {r4, r5, r6, pc}
ldr r3, [r4, #8]
cmp r3, #0
beq .L27
ldr r1, .L34
mov r2, #3
mov r0, r1
blx r3
.L27:
bl __cxa_end_cleanup
.L34:
.word .LANCHOR1
.word Thing::function(char const*)
.word .LC0
.word std::_Function_handler<void (), std::_Bind<void (Thing::*(Thing*, char const*))(char const*)> >::_M_invoke(std::_Any_data const&)
.word std::_Function_base::_Base_manager<std::_Bind<void (Thing::*(Thing*, char const*))(char const*)> >::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation)
Thing::bar():
ldr r2, .L38
sub sp, sp, #8
stm sp, {r0, r2}
add r2, sp, #8
ldr r3, .L38+4
ldmdb r2, {r0, r1}
ldr ip, .L38+8
ldr r2, .L38+12
stm r3, {r0, r1}
str ip, [r3, #12]
str r2, [r3, #8]
add sp, sp, #8
bx lr
.L38:
.word .LC0
.word .LANCHOR1
.word std::_Function_handler<void (), Thing::bar()::{lambda()#1}>::_M_invoke(std::_Any_data const&)
.word std::_Function_base::_Base_manager<Thing::bar()::{lambda()#1}>::_M_manager(std::_Any_data&, std::_Function_base::_Base_manager<Thing::bar()::{lambda()#1}> const&, std::_Manager_operation)
Thing::foo():
mov r3#0
推送{r4,r5,r6,lr}
ldr r4、.L34
mov r6,r0
副警司,警司,#16
mov r0,#16
str r3[r4,#8]
bl运算符新(无符号整数)
ldr r2、.L34+4
移动r1,#0
mov r3,r0
strr2[sp]
莫夫r2,sp
ldr r5、.L34+8
ldr lr,.L34+12
ldr ip,.L34+16
str r1[sp,#4]
str r6[r0,#12]
strr0[r4]
str r5[r3,#8]
ldmr2,{r0,r1}
str lr[r4,#12]
stm r3,{r0,r1}
str ip,[r4,#8]
添加sp,sp,#16
pop{r4,r5,r6,pc}
ldr r3,[r4,#8]
cmp r3,#0
贝基L27
ldr r1、.L34
第2节第3节
mov r0,r1
blx r3
.L27:
bl\uuuu cxa\u end\u清理
.L34:
.单词.兰乔1
.word Thing::函数(char const*)
.word.LC0
.word std::_函数_处理程序::_调用(std:_任意_数据常量&)
.word std::_Function_base::_base_manager::_M_manager(std:_Any_data&,std:_Any_data const&,std:_manager_operation)
Thing::bar():
ldr r2,.L38
副警司,警司,#8
stm sp,{r0,r2}
加上r2,sp,#8
ldr r3、.L38+4
ldmdb r2,{r0,r1}
ldr ip,.L38+8
ldr r2、.L38+12
stm r3,{r0,r1}
str ip,[r3,#12]
str r2[r3,#8]
添加sp、sp、#8
bx-lr
.L38:
.word.LC0
.单词.兰乔1
.word std::_函数_处理程序::_调用(std:_任意_数据常量&)
word std::_函数_base::_base _manager::_M_manager(std:_Any_data&,std:_函数_base:_base):_managerconst&,std:_manager(操作)
我们可以清楚地看到在bind情况下有内存分配,但在lambda情况下没有
*尽管名称由g++和clang++在许多不同的体系结构中使用。“为了效率,我可能”你不应该这样假设效率。使用
std::list
会在每次向列表中添加项目时导致内存分配。很好的“效率”。到目前为止,您所做的分析是否表明这段特定代码是性能瓶颈或内存占用?@kbok我不是在做假设,它是在收集数据库
#include <functional>
using namespace std;
class Thing
{
void foo();
void bar();
void function (const char * message);
};
char baz[1024];
void Thing::foo() {
new (baz) std::function<void()>(std::bind(&Thing::function, this, "Hello"));
}
void Thing::bar() {
const char * s = "Hello";
new (baz) std::function<void()>([this,s](){function(s);});
}
Thing::foo():
mov r3, #0
push {r4, r5, r6, lr}
ldr r4, .L34
mov r6, r0
sub sp, sp, #16
mov r0, #16
str r3, [r4, #8]
bl operator new(unsigned int)
ldr r2, .L34+4
mov r1, #0
mov r3, r0
str r2, [sp]
mov r2, sp
ldr r5, .L34+8
ldr lr, .L34+12
ldr ip, .L34+16
str r1, [sp, #4]
str r6, [r0, #12]
str r0, [r4]
str r5, [r3, #8]
ldm r2, {r0, r1}
str lr, [r4, #12]
stm r3, {r0, r1}
str ip, [r4, #8]
add sp, sp, #16
pop {r4, r5, r6, pc}
ldr r3, [r4, #8]
cmp r3, #0
beq .L27
ldr r1, .L34
mov r2, #3
mov r0, r1
blx r3
.L27:
bl __cxa_end_cleanup
.L34:
.word .LANCHOR1
.word Thing::function(char const*)
.word .LC0
.word std::_Function_handler<void (), std::_Bind<void (Thing::*(Thing*, char const*))(char const*)> >::_M_invoke(std::_Any_data const&)
.word std::_Function_base::_Base_manager<std::_Bind<void (Thing::*(Thing*, char const*))(char const*)> >::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation)
Thing::bar():
ldr r2, .L38
sub sp, sp, #8
stm sp, {r0, r2}
add r2, sp, #8
ldr r3, .L38+4
ldmdb r2, {r0, r1}
ldr ip, .L38+8
ldr r2, .L38+12
stm r3, {r0, r1}
str ip, [r3, #12]
str r2, [r3, #8]
add sp, sp, #8
bx lr
.L38:
.word .LC0
.word .LANCHOR1
.word std::_Function_handler<void (), Thing::bar()::{lambda()#1}>::_M_invoke(std::_Any_data const&)
.word std::_Function_base::_Base_manager<Thing::bar()::{lambda()#1}>::_M_manager(std::_Any_data&, std::_Function_base::_Base_manager<Thing::bar()::{lambda()#1}> const&, std::_Manager_operation)