当一个类既有移动构造函数,又有拷贝构造函数时,编译器使用普通的函数匹配规则来确定使用哪个构造函数,赋值操作的情况类似,即是说,当参数是左值时就调用拷贝构造函数,当参数是右值时就调用移动构造函数。
但是如果没有移动构造函数,参数为右值也会调用拷贝构造函数。
移动迭代器:
新标准中定义了一种移动迭代器适配器。一个移动迭代器通过改变给定迭代器的解引用运算符的行为来适配次迭代器。一般来说一个迭代器的解引用运算符返回一个指向元素的左值,但是一个移动迭代器的解引用运算符生成一个右值引用。
通过调用标准库的make_move_iterator函数将一个普通迭代器装换为一个移动迭代器:
//假设将一个容器str1的元素移动到另一个容器str2中
auto str2 = alloc.allocate(size);
std::uninitialized_copy(std::make_move_iterator(str1),
std::make_move_iterator(str1 + size),
str2);
//删除旧内存
for(int i = 0;i<size;i++){
alloc.destory(str1 + i); //析构对象
}
alloc.deallocate(str1,size); //释放内存
引用限定符:
有时我们不希望对右值进行赋值,因为可能导致以外的错误,在新标准中可以强制左侧对象是一个左值,其定义方式与定义const成员函数相同,即在参数列表后面加一个引用限定符:
class Foo{
public:
Foo& operator=(const Foo& rhs) &; //只能向可修改的左值赋值
}
引用限定符可以是&和&&,分别指出this指针指向左值或者右值。类似const限定符,引用限定符只能用于非static成员函数,且必须同时出现在函数的声明和定义中。一个函数也可以同时使用const和引用限定符,规定引用限定符必须出现在const限定符之后:
class Foo{
public:
Foo someMem() const &;
}
如果一个成员函数有引用限定符,则重载的有相同参数列表的成员函数都必须有引用限定符:
Foo sorted() &; //具有引用限定符的成员函数
Foo sorted() const &; //相同参数列表,都需要有引用限定符
Foo sorted(int); //不同参数列表的重载,不必有引用限定符