我对std :: move的东西感到很困惑。假设我有这个 一段代码:
string foo() {
string t = "xxxx";
return t;
}
string s = foo();
调用字符串构造函数的次数是多少?是2还是3? 编译器是否会对此行使用move?
string s = foo();
如果是这样,在函数中我甚至没有返回rvalue引用,那怎么可能呢 编译器调用移动构造函数?
答案 0 :(得分:4)
这取决于编译器。在这种情况下,标准要求至少有一个构造函数调用。即,构造t
。
但该标准允许另外两个的可能性:从foo
移动构建t
的值输出,以及从s
移动构造foo
t
。大多数体面的编译器都会通过在s
的内存中直接构造&&
来放弃这些构造函数。这种优化是可能的,因为如果编译器选择不这样做,标准允许不调用这些构造函数。
这称为复制/移动“省略”。
如果是这样,在函数中我甚至没有返回rvalue引用,那么编译器怎么能调用move构造函数呢?
你似乎在误解&&
意味着“移动”,并且如果某处没有move
,那么就不会发生这种运动。或者移动构造需要&&
,这也不是真的。
C ++的指定方式使某些地方的某些表达式被认为是有效的。这意味着值或引用将在绑定到&
参数之前尝试绑定到&&
参数。例如,Temporaries将在const&
之前优先绑定到T
参数。这就是为什么用于构造该类型值的临时工具将被移除。
如果你有一个返回某种类型return x
的值的函数,并且返回表达式的格式为x
,其中T
是{{1}类型的命名变量自动存储持续时间(即:函数参数或堆栈变量),然后标准要求此返回表达式移动构造从x
返回的值。
foo
的返回值是暂时的。 C ++规则要求临时值在&&
之前绑定到const&
参数。因此,您将构建移动到s
。