网站建设业务员好做吗网站关键词基础排名怎么做
- 作者: 五速梦信息网
- 时间: 2026年04月20日 07:43
当前位置: 首页 > news >正文
网站建设业务员好做吗,网站关键词基础排名怎么做,网站开发的岗位与分工,七牛 wordpress 媒体文章目录一、左值引用、 右值引用1.1 左值与右值1.2 左值引用1.3 右值引用二、右值引用的意义三、移动语句3.1 移动构造3.2 移动赋值3.3 总结四、move问题五、完美转发5.1 万能引用与折叠5.2 完美转发std::forward一、左值引用、 右值引用
1.1 左值与右值
我们经常能听到左值…
文章目录一、左值引用、 右值引用1.1 左值与右值1.2 左值引用1.3 右值引用二、右值引用的意义三、移动语句3.1 移动构造3.2 移动赋值3.3 总结四、move问题五、完美转发5.1 万能引用与折叠5.2 完美转发std::forward一、左值引用、 右值引用
1.1 左值与右值
我们经常能听到左值和右值那么我们怎么判断左值和右值呢 C中还有一个被广泛认同的说法 那就是可以取地址的、 有名字的就是左值 反之不能取地址的、 没有名字的就是右值。 左值可以出现在左边和右边而右值不能出现在左边。 举个例子 a是个左值ab就是个右值 因为可以对a取地址a 但是不能对a b取地址(a b)
左值和右值不是个变量而是个数据表达式。 左值一般有变量名或解引用的指针 右值一般有字面常量、表达式返回值函数返回值
1.2 左值引用
左值引用就是给左值起别名。
int main()
{// 左值int a 0;int* b nullptr;const int c 1;const int* d nullptr;// 左值引用int ra a;int* rb b;const int rc c;const int* rd d;// 左值引用不能引用右值但const左值引用可以//int e 10;//int f (a c);const int e 10;const int f (a c);return 0;
}1.3 右值引用
右值引用只能引用右值不能引用左值。 但是右值引用可以move以后的左值move可以把ret变成一个将亡值(右值)。
int main()
{// 只能引用右值int a 10;a;// 右值引用后变左值int ret 0;//int b ret;// 不能引用左值// 可以引用move后的左值int b std::move(ret);return 0;
}const引用既可以引用左值也可以引用右值。
二、右值引用的意义
我们以前使用的引用基本上都是左值引用函数传参函数传返回值左值引用的作用主要用来减少拷贝。 但是左值引用并没有彻底的解决传返回值的时候如果是一个局部变量我们就无法引用返回了。
template class T
T fun()
{T a;return a;
}这里出了作用域后对象自动销毁所以不能传递回去造成越界访问。 为了解决这种情况我们就需要右值引用接下来用我们之前写过的string类举例子方便观察。
namespace yyh
{class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str _size;}string(const char* str ):_size(strlen(str)), _capacity(_size){_str new char[_capacity 1];strcpy(_str, str);}void swap(string s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}// 拷贝构造string(const string s){cout string(const string s) – 深拷贝 endl;string tmp(s._str);swap(tmp);}// 赋值重载string operator(const string s){cout string operator(string s) – 深拷贝 endl;string tmp(s);swap(tmp);return this;}~string(){delete[] _str;_str nullptr;}char operator{assert(pos _size);return _str[pos];}void reserve(size_t n){if (n _capacity){char tmp new char[n 1];strcpy(tmp, _str);delete[] _str;_str tmp;_capacity n;}}void push_back(char ch){if (_size _capacity){size_t newcapacity _capacity 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] ch;_size;_str[_size] \0;}string operator(char ch){push_back(ch);return this;}const char c_str() const{return _str;}private:char* _str nullptr;size_t _size 0;size_t _capacity 0;};string Get(){string s 123456;return s;}
}int main()
{yyh::string ret yyh::Get();return 0;
}这里本来应该是Get返回的时候先拷贝一个临时对象再用这个临时对象拷贝给ret但是编译器经过优化可以直接拷贝给ret只调用一次拷贝构造。 不经过优化 如果对象较小就放到寄存器如果较大就在两个栈帧之间创建一个栈帧压返回值。 但是就算经过了优化也还是要拷贝如果要返回的对象非常大就会有大消耗。
三、移动语句
3.1 移动构造
右值又分为纯右值和将亡值 纯右值内置类型的表达式的值。 将亡值自定义类型表达式的值。 对于一个将亡值与其让它消失还不如直接把它的值交换走换给有需要的对象。 所以我们可以写一个拷贝构造的重载。
// 拷贝构造
string(const string s)
{cout string(const string s) – 深拷贝 endl;string tmp(s._str);swap(tmp);
}// 移动构造
string(string s)
{cout string(string s) – 移动拷贝 endl;swap(s);
}这里如果是左值就会匹配拷贝构造如果是右值就会匹配移动构造。
结果 3.2 移动赋值
上边解决了拷贝的问题接下来解决赋值问题。 这里会调用string(const string s)是因为operator使用的是现代写法。
// 赋值重载
string operator(const string s)
{cout string operator(string s) – 深拷贝 endl;string tmp(s);swap(tmp);return *this;
}// 移动赋值
string operator(string s)
{cout string operator(string s) – 移动赋值 endl;swap(s);return *this;
}3.3 总结
左值引用和右值引用减少拷贝的方式不太一样。 左值引用是直接取别名。 右值引用是使用移动构造和移动拷贝间接实现可以把要返回的临时对象看作将亡值进行资源转移。 右值引用主要解决的是对象传值返回拷贝问题。也可以解决容器插入数据的拷贝问题如果插入的是右值就不需要深拷贝。
四、move问题
我们知道move可以把一个左值变成右值但是有可能会出现问题
int main()
{yyh::string s1(aaaaa);yyh::string s2(std::move(s1));return 0;
}移动构造把资源转移后原来的对象的资源就消失了。
void fun2(int i)
{cout fun2(int i) endl;
}void fun2(int i)
{cout fun2(int i) endl;
}void fun1(int i)
{cout fun1(int i) endl;fun2(i);
}int main()
{fun1(1);return 0;
}这里为什么在fun1函数中没有调用void fun2(int i)呢 因为右值引用后就会变成左值而左值就会对应调用void fun2(int i)。 如果我们想让fun1调用void fun2(int i)
void fun1(int i)
{cout fun1(int i) endl;fun2(std::move(i));
}但是如果有多层嵌套函数就会频繁使用move所以C11引入新语法完美转发std::forward
五、完美转发
5.1 万能引用与折叠
上面我们区分左值和右值是通过两个函数的参数来区分。 在普通函数里右值不能引用左值
void fun1(int i)
{cout fun1(int i) endl;
}int main()
{int a 1;//fun1(a);// 右值不能引用左值return 0;
}所以C11提供了万能引用
// 万能引用
template class T
void fun(T i)
{cout fun(int i) endl;
}int main()
{int a 1;fun(a);// 左值fun(std::move(a));// 右值const int b 1;fun(b);// const左值fun(std::move(b));// const右值return 0;
}这样就可以既引用左值/const左值 也可以引用右值/const右值。 完美转发是指在函数模板中完全依照模板的参数的类型将参数传递给函数模板中调用的另外一个函数。 实例化出以下类型的不同函数
5.2 完美转发std::forward
void Fun(int x) { cout 左值引用 endl; }
void Fun(const int x) { cout const 左值引用 endl; }void Fun(int x) { cout 右值引用 endl; }
void Fun(const int x) { cout const 右值引用 endl; }// 万能引用
template class T
void fun(T i)
{Fun(i);
}int main()
{int a 1;fun(a);// 左值fun(std::move(a));// 右值const int b 1;fun(b);// const左值fun(std::move(b));// const右值return 0;
}我们可以看出这个fun函数把所有的全部转化为左值不是我们想要的。 所以就有了完美转发std::forward 完美转发适用于这样的场景 需要将一组参数原封不动的传递给另一个函数。 而且原封不动传递的不仅仅是参数的数值还包括左值/右值const/非const这些性质。
// 万能引用
void Fun(int x) { cout 左值引用 endl; }
void Fun(const int x) { cout const 左值引用 endl; }void Fun(int x) { cout 右值引用 endl; }
void Fun(const int x) { cout const 右值引用 endl; }// 万能引用
template class T
void fun(T i)
{// 完美转发保持原本属性Fun(std::forwardT(i));
}int main()
{int a 1;fun(a);// 左值fun(std::move(a));// 右值const int b 1;fun(b);// const左值fun(std::move(b));// const右值return 0;
}
- 上一篇: 网站建设业务培训资料用什么网站做问卷
- 下一篇: 网站建设业务知识培训资料有没有免费的推广网站
相关文章
-
网站建设业务培训资料用什么网站做问卷
网站建设业务培训资料用什么网站做问卷
- 技术栈
- 2026年04月20日
-
网站建设业务培训怎么做虚拟币网站
网站建设业务培训怎么做虚拟币网站
- 技术栈
- 2026年04月20日
-
网站建设业务范围成都市网站建设公司
网站建设业务范围成都市网站建设公司
- 技术栈
- 2026年04月20日
-
网站建设业务知识培训资料有没有免费的推广网站
网站建设业务知识培训资料有没有免费的推广网站
- 技术栈
- 2026年04月20日
-
网站建设页面wordpress 文章列表主题
网站建设页面wordpress 文章列表主题
- 技术栈
- 2026年04月20日
-
网站建设页面底部叫什么重庆交通网站建设
网站建设页面底部叫什么重庆交通网站建设
- 技术栈
- 2026年04月20日
