当前位置: 首页 > news >正文

大庆市城乡建设局网站wordpress计数ip

大庆市城乡建设局网站,wordpress计数ip,网站模板定制,南宁网站推广经理【C随笔02】左值和右值 一、左值和右值1、字面理解——左值、右值2、字面理解的问题3、左值、右值4、左值的特征5、 右值的特征6、x和x是左值还是右值7、复合例子8、通常字面量都是一个右值#xff0c;除字符串字面量以外#xff1a; 二、左值引用和右值引用三、左值引用1、常… 【C随笔02】左值和右值 一、左值和右值1、字面理解——左值、右值2、字面理解的问题3、左值、右值4、左值的特征5、 右值的特征6、x和x是左值还是右值7、复合例子8、通常字面量都是一个右值除字符串字面量以外 二、左值引用和右值引用三、左值引用1、常量左值引用2、制构造函数和复制赋值运算符函数——左值引用 四、右值引用1、移动语义和完美转发2、移动语义3、完美转发3.1、简介、demo3.2、问题:c中的完美转发std::forward存在的意义 简单总结 一、左值和右值 1、字面理解——左值、右值 最简单的字面理解表达式等号左边的值为左值等号右边的值为右值比如 int x 1; int y 3; int z x y;以上面的代码为例 x是左值1是右值y是左值3是右值z是左值xy的结果是右值。(注意是结果) 2、字面理解的问题 在第一行代码中我们判断a是一个左值它却在第二行变成了右值所以这就是问题要准确地区分左值和右值还是应该理解其内在含义。 3、左值、右值 在C中 左值一般是指一个指向特定内存的具有名称的值具名对象它有一个相对稳定的内存地址并且有一段较长的生命周期。右值则是不指向稳定内存地址的匿名值不具名对象 简单来说左值是一个有内存地址的表达式而右值是一个没有内存地址的表达式。 基于这一特征我们可以用取地址符来判断左值和右值能取到内存地址的值为左值否则为右值。还是以上面的代码为例因为a和b都是符合语法规则的所以a和b都是左值。 4、左值的特征 左值具有以下特征 左值在内存中有唯一的地址。左值可以出现在赋值操作符的左边。左值可以被取地址操作符获取其内存地址。左值可以作为函数参数或返回值。 int x 10; // x是一个左值 int* ptr x; // 获取x的地址并赋给指针ptr5、 右值的特征 右值具有以下特征 右值没有内存地址。右值不能作为赋值操作符的左边。右值不能被取地址操作符获取其内存地址。 int y 20; // 20是一个右值 int z x y; // 表达式x y的结果是一个右值6、x和x是左值还是右值 int *p x; // 编译失败 int *q x; // 编译成功x是右值因为在后置操作中编译器首先会生成一份x值的临时复制然后才对x递增最后返回临时复制内容。x则不同它是直接对x递增后马上返回其自身所以x是一个左值。 7、复合例子 int x 1; int get_val() {return x; } void set_val(int val) {x val; } int main() {x;x;int y get_val();set_val(6); }get_val函数该函数返回了一个全局变量x虽然很明显变量x是一个左值但是它经过函数返回以后变成了一个右值。 原因和x类似在函数返回的时候编译器并不会返回x本身而是返回x的临时复制所以int * p get_val();也会编译失败。 set_val函数该函数接受一个参数并且将参数的值赋值到x中。在main函数中set_val(6);实参6是一个右值但是进入函数之后形参val却变成了一个左值。 我们可以对val使用取地址符. 左值到右值的隐式转换 左值可以被隐式地转换为右值例如在某些表达式中需要右值而传入一个左值参数时编译器会自动进行转换。 void printValue(int value) {cout value endl; }int x 10; printValue(x); // 编译器将x隐式地转换为右值传递给函数8、通常字面量都是一个右值除字符串字面量以外 int x 1; set_val(6); auto p “hello world”; 编译器会将字符串字面量存储到程序的数据段中程序加载的时候也会为其开辟内存空间(rodata)所以我们可以使用取地址符来获取字符串字面量的内存地址。 给大家写一个有编译错误的例子大家调调 #include iostreamint add1(int x) {return x1; }int main() {int a add1(1);std::cout a std::endl;return 0; }二、左值引用和右值引用 void processValue(int value) {// 对左值进行处理 }void processValue(int value) {// 对右值进行处理 }左值引用和右值引用在C11中引入了右值引用的概念。左值引用L-value references用于绑定到左值右值引用R-value references用于绑定到右值。 左值引用的声明使用单个符号 int x 10; int lvalueRef x; // 左值引用绑定到左值x右值引用的声明使用两个符号 int y 20; int rvalueRef y 30; // 右值引用绑定到右值表达式的结果引用可以方便地对变量进行修改或者将其传递给函数。 右值引用在移动语义Move Semantics和完美转发Perfect Forwarding中具有重要的作用可以提高性能和代码效率。 三、左值引用 1、常量左值引用 常量左值引用的特性显得更加有趣它除了能引用左值还能够引用右值比如 int x1 7; // 编译错误 const int x 11; // 编译成功在上面的代码中第一行代码会编译报错因为int无法绑定一个int类型的右值但是第二行代码却可以编译成功。请注意虽然在结果上const int x 11和const int x 11是一样的但是从语法上来说前者是被引用了所以语句结束后11的生命周期被延长而后者当语句结束后右值11应该被销毁。虽然常量左值引用可以引用右值的这个特性在赋值表达式中看不出什么实用价值但是在函数形参列表中却有着巨大的作用。一个典型的例子就是复制构造函数和复制赋值运算符函数 2、制构造函数和复制赋值运算符函数——左值引用 当我们使用左值引用时通常会涉及到复制构造函数和复制赋值运算符函数。复制构造函数用于创建一个新对象并将其初始化为已存在的对象的副本。复制赋值运算符函数用于将一个已存在的对象的值复制给另一个已存在的对象。 以下是一个简单的示例程序演示了左值引用、复制构造函数和复制赋值运算符函数的使用 #include iostreamclass MyObject { private:int data;public:MyObject(int d) : data(d) {std::cout Constructor called with value: d std::endl;}MyObject(const MyObject other) : data(other.data) {std::cout Copy constructor called. Copied value: data std::endl;}MyObject operator(const MyObject other) {if (this ! other) {data other.data;std::cout Copy assignment operator called. Copied value: data std::endl;}return *this;}void printData() const {std::cout Data: data std::endl;} };int main() {MyObject obj1(42); // 调用构造函数MyObject obj2(obj1); // 调用复制构造函数MyObject obj3 obj1; // 调用复制构造函数MyObject obj4(55); // 调用构造函数obj4 obj1; // 调用复制赋值运算符函数obj1.printData(); // 输出: Data: 42obj2.printData(); // 输出: Data: 42obj3.printData(); // 输出: Data: 42obj4.printData(); // 输出: Data: 42return 0; }输出 Constructor called with value: 42 Copy constructor called. Copied value: 42 Copy constructor called. Copied value: 42 Constructor called with value: 55 Copy assignment operator called. Copied value: 42 Data: 42 Data: 42 Data: 42 Data: 42 在上述示例中我们首先定义了一个名为 MyObject 的类该类具有一个带有整数参数的构造函数、一个复制构造函数和一个复制赋值运算符函数。然后我们创建了几个 MyObject 类型的对象并通过不同方式进行初始化和赋值。 在 main() 函数中我们创建了 obj1并使用拷贝构造函数将其值分别复制给 obj2 和 obj3。接下来我们创建了 obj4然后使用赋值运算符将 obj1 的值复制给 obj4。 最后我们调用各个对象的成员函数 printData() 来打印它们的数据值。你可以看到obj2、obj3 和 obj4 的数据值都与 obj1 相同这表明复制构造函数和复制赋值运算符函数成功地将一个对象的值复制给了另一个对象。 四、右值引用 顾名思义右值引用是一种引用右值且只能引用右值的方法。在语法方面右值引用可以对比左值引用在左值引用声明中需要在类型后添加而右值引用则是在类型后添加例如 int i 0; int j i; // 左值引用 int k 11; // 右值引用在上面的代码中k是一个右值引用如果试图用k引用变量i则会引起编译错误。右值引用的特点之一是可以延长右值的生命周期。 1、移动语义和完美转发 右值引用在移动语义和完美转发中起着重要的作用。 移动语义移动语义是指通过右值引用将资源如动态分配的内存、文件句柄等从一个对象转移到另一个对象而不是进行深拷贝。这样可以避免不必要的内存分配和释放提高程序性能。 完美转发完美转发是指将一个函数中的参数以原样传递给另一个函数包括参数的左值或右值属性信息。通过使用右值引用和模板可以实现完美转发避免了不必要的拷贝。 2、移动语义 当涉及到移动语义和完美转发时我们需要先了解一些基本概念和问题。在C中对象的拷贝构造函数Copy Constructor和拷贝赋值运算符Copy Assignment Operator会对资源进行拷贝操作这可能导致内存分配和释放的开销。在某些情况下我们希望能够高效地转移资源的所有权而不是进行深拷贝这就引入了移动语义和完美转发。 移动语义Move Semantics 移动语义是指通过右值引用将资源如动态分配的内存、文件句柄等从一个对象转移到另一个对象而不是进行深拷贝。移动语义可以大大提高程序性能因为它避免了不必要的内存分配和释放。 移动语义的实现依赖于右值引用。右值引用R-value Reference通过双个符号进行声明并且可以绑定到右值。通过移动构造函数Move Constructor和移动赋值运算符Move Assignment Operator可以使用移动语义来实现资源的高效转移。 简单来说移动语义允许我们从一个临时的右值对象或者一个将要被销毁的对象中“窃取”资源然后将其传递给新对象而无需进行资源的复制操作。 示例代码 #include iostreamclass MyObject { private:int data;public:MyObject(int d 0) : data(d) {std::cout Constructor called with value: d std::endl;}MyObject(const MyObject other) : data(other.data) {std::cout Copy constructor called. Copied value: data std::endl;}MyObject operator(const MyObject other) {if (this ! other) {data other.data;std::cout Copy assignment operator called. Copied value: data std::endl;}return *this;}MyObject(MyObject other) noexcept : data(other.data) {std::cout Move constructor called. Moved value: data std::endl;other.data 0; // 清空原对象的值}MyObject operator(MyObject other) noexcept {if (this ! other) {data other.data;std::cout Move assignment operator called. Moved value: data std::endl;other.data 0; // 清空原对象的值}return *this;}void printData() const {std::cout Data: data std::endl;} };int main() {MyObject obj1(42); // 调用构造函数MyObject obj2(obj1); // 调用复制构造函数MyObject obj3 obj1; // 调用复制构造函数MyObject obj4(55); // 调用构造函数obj4 obj1; // 调用复制赋值运算符函数MyObject obj5(std::move(obj1)); // 调用移动构造函数MyObject obj6 std::move(obj2); // 调用移动赋值构造函数obj1.printData(); // 输出: Data: 42obj2.printData(); // 输出: Data: 0obj3.printData(); // 输出: Data: 42obj4.printData(); // 输出: Data: 42obj5.printData(); // 输出: Data: 42obj6.printData(); // 输出: Data: 42return 0; }Constructor called with value: 42 Copy constructor called. Copied value: 42 Copy constructor called. Copied value: 42 Constructor called with value: 55 Copy assignment operator called. Copied value: 42 Move constructor called. Moved value: 42 Move constructor called. Moved value: 42 Data: 0 Data: 0 Data: 42 Data: 42 Data: 42 Data: 42 obj1和obj2为0这证明了移动构造函数被调用并且资源成功被转移。 3、完美转发 3.1、简介、demo 完美转发perfect forwarding是C11引入的概念用于在函数模板中将参数按原样传递给另一个函数同时保留其值类别lvalue或rvalue。它可以在保持精确性的同时避免不必要的复制或移动操作提高代码的效率。 完美转发通常与转发引用类型参数如模板中的万能引用一起使用以实现泛型编程中的参数传递。在函数模板中我们可以使用 std::forward 函数来进行完美转发。 下面是一个使用完美转发的示例 #include iostream #include utility// 定义一个接收传入参数的函数 void process(int i) {std::cout Lvalue: i std::endl;i 100; // 修改传入的左值参数 }void process(int i) {std::cout Rvalue: i std::endl; }// 将参数转发到 process 函数 template typename T void wrapper(T arg) {process(std::forwardT(arg)); }int main() {int a 42;wrapper(a); // 传递左值wrapper(123); // 传递右值std::cout a: a std::endl;int b 42;process(b);process(123);std::cout b: a std::endl;return 0; }输出 Lvalue: 42 Rvalue: 123 a: 100 Lvalue: 42 Rvalue: 123 b: 100 在上述示例中我们定义了两个重载的 process 函数一个接受左值引用参数一个接受右值引用参数。然后我们创建了一个模板函数 wrapper该函数接受一个通用引用类型的参数 T arg。 在 wrapper 函数内部我们通过调用 std::forward 来进行完美转发将 arg 参数原封不动地传递给 process 函数。std::forward 根据参数的值类别lvalue还是rvalue将参数作为对应类型的引用进行转发。 在 main 函数中我们先传递了一个左值 x 给 wrapper 函数然后传递了一个右值 123。程序会根据参数的值类别选择调用合适的 process 函数并输出相应的结果。 使用完美转发可以避免不必要的拷贝和移动操作提高代码的效率和性能。 3.2、问题:c中的完美转发std::forward存在的意义 我们从上面的demo中可以看到既然不使用forward也可以达到类似的效果那为何还要使用完美转发std::forward呢 说这个问题前我们先把上面的一个demo改下 #include iostreamclass MyObject { private:int data;public:MyObject(int d 0) : data(d) {std::cout Constructor called with value: d std::endl;}MyObject(const MyObject other) : data(other.data) {std::cout Copy constructor called. Copied value: data std::endl;}MyObject operator(const MyObject other) {if (this ! other) {data other.data;std::cout Copy assignment operator called. Copied value: data std::endl;}return *this;}MyObject(MyObject other) noexcept : data(other.data) {std::cout Move constructor called. Moved value: data std::endl;other.data 0; // 清空原对象的值}MyObject operator(MyObject other) noexcept {if (this ! other) {data other.data;std::cout Move assignment operator called. Moved value: data std::endl;other.data 0; // 清空原对象的值}return *this;}void printData() const {std::cout Data: data std::endl;} };templatetypename T T* createObject(T t) {return new MyObject(t); }int main() {MyObject* newMyObject createObject(std::move(MyObject(110)));return 0; }大家猜猜看上面应该输出什么应该调用移动构造函数的对吧实际情况输出如下调用的却是拷贝构造函数。 Constructor called with value: 110 Copy constructor called. Copied value: 110 是不是很好奇为啥调用的是拷贝构造函数而非我们之前想象的移动构造函数呢 我们把createObject做下简单的更改增加std::forward templatetypename T T* createObject(T t) {return new MyObject(std::forwardT(t)); }结果输出如下 Constructor called with value: 110 Move constructor called. Moved value: 110 这时才真正的如我们所想真的调用了移动构造函数。 分析经历了模版参数t这一次转发t右值的属性被改变为了左值。 简单总结 左值引用用于引用左值并允许修改右值引用用于引用右值并具有移动语义和完美转发的特性。
http://www.w-s-a.com/news/155211/

相关文章:

  • 论坛网站开发网络营销是什么时候产生的
  • 帮人做网站赚钱无忧软文网
  • 做网站要不要营业执照重庆网站优化seo公司
  • 学院宣传网站建设简介做网站没灵感
  • 网站建设终稿确认书网站意义学校
  • 3小时网站建设平台专业制作教学课件
  • 曲阜网站建设百度开户现货黄金什么网站可以做直播
  • 比较好的企业建站平台小程序开发外包该注意些什么
  • 建行官网官网网站吗二次元风格wordpress模板
  • 怎样开通自己的网站网址导航哪个主页最好
  • 大良o2o网站建设详情页设计说明怎么写
  • 您与此网站之间建立的连接不安全汽车cms系统是什么意思
  • 有没有做logo的网站企业网站的内容营销
  • 哈尔滨做企业网站怎么做网站自动响应
  • 网站建设硬件和软件技术环境配置签约做网站模板
  • 教育网站建设的素材手机app制作流程
  • 免费行情软件网站大全下载网站备案查询
  • flex网站模板wordpress实时预览
  • 建设银行网站模板为什么企业要建设自己的企业文化
  • 网站建设必知免费手机网站建站系统
  • ssh可以做wap网站么嘉兴seo排名
  • 站内优化包括哪些帝国做企业网站
  • 做网站seo赚钱吗网络维护和故障维修
  • 企业网站可以自己做摄影网站开发背景怎么写
  • 网站百度指数seo最好的工具
  • 宝安专业网站建设推荐设计感强的网站
  • 网站建设 6万元北京知名的品牌设计公司
  • 网站建设的总体需求是什么vmware 下wordpress
  • 光谷网站建设请检查网络
  • 申请建设网站的报告书商务网站开发课程体会