-
Notifications
You must be signed in to change notification settings - Fork 0
Description
右值:
字面量(如10, 'a')和临时对象(如A())
"区分左值和右值的一个简单办法是:看能不能对表达式取地址,如果能,则为左值,否则为右值。"
const A& 和A&& 都会引用到临时对象,但是A&&的优先级更高
auto a = A();不会调用copy/move constructor,只会调用普通的constructor,实际上就是在栈上分配一块空间,执行构造函数,只有一个对象,等价于A a();
而a = A();(a是一个已有对象)会调用copy/move assignment,因为存在两个对象:先构造一个临时对象A(),再赋值给a,如果A有move assignment,则优先调用move assignment
值得注意的是,foo_by_value(A())不会调用copy/move constructor,仍然是栈上构造一个对象,类似auto a = A();
foo_by_value(a)永远会调用copy constructor
foo_by_ref(A()),foo_by_ref(const A&)和foo_by_ref(A&&)都合法,两者都存在时优先匹配A&&
对于返回值是struct的函数,编译器有return slot优化,直接在父函数的栈帧上构造对象,而不是现在本函数构造对象,再拷贝给父函数,编译器会把父函数栈帧上return slot的地址传给本函数
auto a = foo() {return A();} 不会调用copy/move constructor,直接在父函数栈帧上用A()构造a
A a = foo() { return A(); }同上
a = foo() { return A(); },现在父函数上构造一个临时对象,然后copy/move assignment给a
a5 = f4(): Copy constructor? -- no
Constructing 0x7fffdb9e7ec0 with parm 5
[Enter f4]:
-- outside
Move assignment: &other = 0x7fffdb9e7ec0, other.a = 5, this = 0x7fffdb9e7ea8, this->a = 5
重点区分:
auto a = A();
auto a = foo() { return A(); }
都不会调copy constructor,只有一次default constructing
foo_by_value(A());
foo_by_value(a);
一个不调copy constructor,一个要调
注:以上结果是g++/clang++默认对构造函数优化的结果,如果加了-fno-elide-constructors,结果会很不一样
那么move constructor的意义是什么?
copy constructor一般是深拷贝,保证两个对象各自拥有独立的资源。而如果src对象是个临时对象,不需要有独立资源时,用move constructor做浅拷贝就好了:
auto a = foo() { return A(); } 或 A a = foo() { return A(); }
move assignment适用场景:
a = A();
a = foo() { return A(); }