C++入门教程之转移语义实例
程序员文章站
2024-01-26 11:03:28
C++入门教程之转移语义实例
这里继续讲左值和右值。
由于标准库中尤其是容器库还有字符串类,对右值进行了特殊的优化:
// 复制右值就等于浪费资源, 所以直接保存右值,...
C++入门教程之转移语义实例
这里继续讲左值和右值。
由于标准库中尤其是容器库还有字符串类,对右值进行了特殊的优化:
// 复制右值就等于浪费资源, 所以直接保存右值, 几乎不耗时间 std::u32string text1 = std::u32string(U"小古银是个美男子"); // 复制text1的字符串, 即复制左值, 字符串越长, 需要的时间就越长 std::u32string text2 = text1;
基础示例
如果我想交换text1和text2保存的值时,举个完整的例子:
#include // std::cout std::endl #include // 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保存的字符串
这三行代码是交换text1和text2的代码。我们知道复制是需要内存和时间的,而现在我们想交换text1和text2,即text1的值给text2,text2的值给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 // std::cout std::endl #include // 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