• Index

转移语义

Reads: 7

这里继续讲左值和右值。

由于标准库中尤其是容器库还有字符串类,对右值进行了特殊的优化:

// 复制右值就等于浪费资源, 所以直接保存右值, 几乎不耗时间
std::u32string text1 = std::u32string(U"小古银是个美男子");

// 复制text1的字符串, 即复制左值, 字符串越长, 需要的时间就越长
std::u32string text2 = text1;

基础示例

如果我想交换text1text2保存的值时,举个完整的例子:

#include <iostream> // std::cout std::endl
#include <string> // std::u32string

int main(void)
{
    std::u32string text1 = std::u32string(U"小古银是个美男子");
    std::u32string text2 = std::u32string(U"小古银不是个大胖小子");
    std::u32string text3; // 用来交换的中间变量

    std::cout << "交换前text1的字符数:" << text1.size() << std::endl;
    std::cout << "交换前text2的字符数:" << text2.size() << std::endl;

    text3 = text1; // text3复制text1保存的字符串
    text1 = text2; // text1复制text2保存的字符串
    text2 = text3; // text2复制text3保存的字符串

    std::cout << "交换后text1的字符数:" << text1.size() << std::endl;
    std::cout << "交换后text2的字符数:" << text2.size() << std::endl;

    return 0;
}

输出结果:

交换前text1的字符数:8
交换前text2的字符数:10
交换后text1的字符数:10
交换后text2的字符数:8

基础讲解

text3 = text1; // text3复制text1保存的字符串
text1 = text2; // text1复制text2保存的字符串
text2 = text3; // text2复制text3保存的字符串

这三行代码是交换text1text2的代码。我们知道复制是需要内存和时间的,而现在我们想交换text1text2,即text1的值给text2text2的值给text1。这个时候,我们就需要转移。以上三行交换代码可以改成以下三行:

text3 = std::move(text1); // text1保存的字符串转移到text3, text1空, text2和text3非空
text1 = std::move(text2); // text2保存的字符串转移到text1, text2空, text1和text3非空
text2 = std::move(text3); // text3保存的字符串转移到text2, text3空, text1和text2非空

这样就可以不需要复制字符串而交换两个变量保存的值了。

我们再深入了解一下转移函数std::move(),他在utility标准库中。

实际上,std::move()的实现的功能很简单:它把传进来的左值还有右值都转换成右值。

std::move()返回实际参数的右值,然后再配合容器库和字符串类对右值的优化,这样就可以实现转移的语义。上面三行代码中,text3 = std::move(text1);text1保存的值转移到text3中,此时text1保存的是空字符,接下来两行代码同理。

由于是字符串类进行了优化,对于基本数据类型,std::move()仅仅只有左值转右值的功能而没有转移的功能。如下:

#include <iostream> // std::cout std::endl
#include <utility> // std::move

int main(void)
{
    int a = 2333;
    int b = std::move(a);
    std::cout << a << std::endl;
    std::cout << b << std::endl;
    return 0;
}

输出结果:

2333
2333

Comments

Make a comment

  • Index

WARNING: You are using an old browser that does not support HTML5. Please choose a modern browser (Chrome / Microsoft Edge / Firefox / Sarafi) to get a good experience.