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

网站开发选题依据成都网站关键词推广

网站开发选题依据,成都网站关键词推广,在深圳做网站平台需要什么备案,广告公司名称推荐b站Cherno的课[86]-[90] 一、C持续集成二、C静态分析三、C的参数计算顺序四、C移动语义五、stdmove与移动赋值操作符 一、C持续集成 Jenkins 商业软件 二、C静态分析 静态分析器会检查你的代码,并尝试检测各种错误,这些错误 可能是你无意中编写的&am…

b站Cherno的课[86]-[90]

  • 一、C++持续集成
  • 二、C++静态分析
  • 三、C++的参数计算顺序
  • 四、C++移动语义
  • 五、stdmove与移动赋值操作符

一、C++持续集成

Jenkins 商业软件
在这里插入图片描述

二、C++静态分析

静态分析器会检查你的代码,并尝试检测各种错误,这些错误
可能是你无意中编写的,有点像代码复查,但不是由人来做

PVS-Studio 商业软件

三、C++的参数计算顺序

(参数求值顺序)
argument evaluation order

未定义的行为
也就是说它会根据编译器的不同而变化,完全依赖于C++编译器将代码转换成机器码的实际实现

#include <iostream>void PrintSum(int a, int b)
{std::cout << a << "+" << b << "=" << (a + b) << std::endl;
}int main()
{int value = 0;PrintSum(value++, value++);std::cin.get();
}

在这里插入图片描述
release模式下的常数折叠

C++标准添加了一个从C++17开始的新规则
后缀表达式必须在别的表达式之前被计算

wandbox.org 在线编译网站

C++的参数计算顺序:没有定义

因为c++实际上并没有提供c++规范,并没有提供一个定义,来说明在这种情况下应该发生什么,参数(形参)或实参应该按照什么顺序求值
但如果你提到c++17说了这两件事不能同时做(同时计算)
那就加分了
也就是说,
它们必须一个接一个地完成

但是再说一次,,这个顺序并没有在规范中定义
这意味着你在技术上无法知道计算顺序是什么

四、C++移动语义

左值与右值
移动语义本质上允许我们移动对象

#include <iostream>class String
{
public:String() = default;String(const char* string){printf("Created!\n");m_Size = strlen(string);m_Data = new char[m_Size];memcpy(m_Data, string, m_Size);}String(const String& other){printf("Copied!\n");m_Size = other.m_Size;m_Data = new char[m_Size];memcpy(m_Data, other.m_Data, m_Size);}~String(){delete m_Data;}void Print(){for (uint32_t i = 0; i < m_Size; i++)printf("%c", m_Data[i]);printf("\n");}private:char* m_Data;uint32_t m_Size;
};class Entity
{
public:Entity(const String& name):m_Name(name){}void PrintName(){m_Name.Print();}
private:String m_Name;
};int main()
{Entity entity(String("wm"));entity.PrintName();std::cin.get();
}

在这里插入图片描述

#include <iostream>class String
{
public:String() = default;String(const char* string){printf("Created!\n");m_Size = strlen(string);m_Data = new char[m_Size];memcpy(m_Data, string, m_Size);}String(const String& other){printf("Copied!\n");m_Size = other.m_Size;m_Data = new char[m_Size];memcpy(m_Data, other.m_Data, m_Size);}String(String&& other) noexcept{printf("Moved!\n");m_Size = other.m_Size;m_Data = other.m_Data;other.m_Size = 0;other.m_Data = nullptr;}~String(){printf("Destroyed!\n");delete m_Data;}void Print(){for (uint32_t i = 0; i < m_Size; i++)printf("%c", m_Data[i]);printf("\n");}private:char* m_Data;uint32_t m_Size;
};class Entity
{
public:Entity(const String& name):m_Name(name){}Entity(String&& name):m_Name(name){}void PrintName(){m_Name.Print();}
private:String m_Name;
};int main()
{Entity entity(String("wm"));entity.PrintName();std::cin.get();
}

在这里插入图片描述

#include <iostream>class String
{
public:String() = default;String(const char* string){printf("Created!\n");m_Size = strlen(string);m_Data = new char[m_Size];memcpy(m_Data, string, m_Size);}String(const String& other){printf("Copied!\n");m_Size = other.m_Size;m_Data = new char[m_Size];memcpy(m_Data, other.m_Data, m_Size);}String(String&& other) noexcept{printf("Moved!\n");m_Size = other.m_Size;m_Data = other.m_Data;other.m_Size = 0;other.m_Data = nullptr;}~String(){printf("Destroyed!\n");delete m_Data;}void Print(){for (uint32_t i = 0; i < m_Size; i++)printf("%c", m_Data[i]);printf("\n");}private:char* m_Data;uint32_t m_Size;
};class Entity
{
public:Entity(const String& name):m_Name(name){}Entity(String&& name)// 只修改了此处,输出Moved//:m_Name((String&&)name):m_Name((std::move)name){}void PrintName(){m_Name.Print();}
private:String m_Name;
};int main()
{Entity entity(String("wm"));entity.PrintName();std::cin.get();
}

在这里插入图片描述

Entity(String&& name)
:m_Name(name)
{
}
这里的问题是,此构造函数的参数name应该是一个右值(String&&),所以m_Name(name)应该是调用的String的移动构造函数,为啥要m_Name(std::move(name)) 才行

因为右值引用在进入函数体内的之后,参数类型会变为左值
也就是在函数体内你可以对 String&& val中的 val取&
所以要触发移动语义必须让他变为右值引用,std::move就是干这个转换的
你看std::move的代码 就是干了一个找到源参数类型的static_cast转换
把参数换成了&&类型
所以就能触发后面的移动构造函数

每个表达式都有两种特征:一是类型二是值类别。
很多人迷惑的右值引用为啥是个左值,那是因为右值引用是它的类型,左值是它的值类别。
想理解右值首先要先知道类型和值类别的区别;其次是各个值类别的定义是满足了某种形式它就是那个类别,经常说的能取地址就是左值,否则就是右值,这是定义之上的不严谨经验总结,换句话说,是左值还是右值是强行规定好的,你只需要对照标准看这个表达式满足什么形式就知道它是什么值类别了。
为什么要有这个分类,是为了语义,当一个表达式出现的形式表示它是一个右值,就是告诉编译器,我以后不会再用到这个资源,放心大胆的转移销毁,这就可以做优化,比如节省拷贝之类的。

move的作用是无条件的把表达式转成右值,也就是rvalue_cast,虽然编译器可以推断出左右值,但人有时比编译器“聪明”,人知道这个表达式的值以后我不会用到,所以可以在正常情况下会推成左值的地方强行告诉编译器,我这是个右值,请你按右值的语义来做事。

五、stdmove与移动赋值操作符

移动语义能够将一个对象移动到另一个对象上
move assignment operator(移动赋值运算符)

#include <iostream>class String
{
public:String() = default;String(const char* string){printf("Created!\n");m_Size = strlen(string);m_Data = new char[m_Size];memcpy(m_Data, string, m_Size);}String(const String& other){printf("Copied!\n");m_Size = other.m_Size;m_Data = new char[m_Size];memcpy(m_Data, other.m_Data, m_Size);}String(String&& other) noexcept{printf("Moved!\n");m_Size = other.m_Size;m_Data = other.m_Data;other.m_Size = 0;other.m_Data = nullptr;}String& operator = (String&& other) noexcept{printf("Moved!\n");if (this != &other){delete[] m_Data;m_Size = other.m_Size;m_Data = other.m_Data;other.m_Size = 0;other.m_Data = nullptr;}return *this;}~String(){printf("Destroyed!\n");delete m_Data;}void Print(){for (uint32_t i = 0; i < m_Size; i++)printf("%c", m_Data[i]);printf("\n");}private:char* m_Data;uint32_t m_Size;
};class Entity
{
public:Entity(const String& name):m_Name(name){}Entity(String&& name):m_Name(std::move(name)){}void PrintName(){m_Name.Print();}
private:String m_Name;
};int main()
{Entity entity(String("wm"));entity.PrintName();String apple = "Apple";String dest;//String string = "Hello";//String dest((String&&)string);//String dest = (String&&)string;//String dest(std::move(string));//String dest = std::move(string);//dest.assign(std::move(string));//dest = std::move(dest);apple.Print();dest.Print();dest = std::move(apple);apple.Print();dest.Print();std::cin.get();
}

在这里插入图片描述

int main()
{String apple = "Apple";String dest;std::cout << "Apple: ";apple.Print();std::cout << "Dest: ";dest.Print();dest = std::move(apple);std::cout << "Apple: ";apple.Print();std::cout << "Dest: ";dest.Print();std::cin.get();
}

在这里插入图片描述
总而言之
移动赋值操作符是你想要包含在类中的东西,当你包含一个移动构造函数时,因为它当然是想要将一个对象移动到一个现有的变量中

它基本上是五法则的一部分,还有三法则,五法则包含了所有的新移动语义

注:
C++三法则:如果需要析构函数,则一定需要拷贝构造函数和拷贝赋值操作符C++五法则:为了支持移动语义,又增加了移动构造函数和移动赋值运算符

赋值操作符与使用构造函数的区别:

通过使用这个运算符,它就像我们写.operator=,并像调用函数一样调用它
std:move是你想要将一个对象转换为临时对象时要做的

换句话说,如果你需要把一个已经存在的变量变成临时变量
你可以标记它,表示你可以从这个特定的变量中窃取资源
这使我们能够在现有的变量上执行移动操作

如果你在创建一个新变量,如果是在函数参数中或在移动构造函数中(创建),那么它已经是一个临时变量,这是可以的

但如果你有一个已经存在的变量,比如这个apple的例子
这是一个已经存在的变量,你需要确保使用std:move来将它转换成一个临时变量
这样你就可以使用移动构造函数或移动赋值操作符,从那个变量中获取资源,并进行移动

http://www.dtcms.com/wzjs/293641.html

相关文章:

  • 布吉企业网站建设最新军事头条
  • 营销类网站建设seo网站权重
  • 中企动力做的网站经常打不开企业整站优化
  • 新疆建设网二级域名网站餐饮营销策划方案
  • 给酒吧做网站时事新闻最新
  • 个人网站开发的现状aso应用商店优化原因
  • 和先锋影音和做的网站百度广告联盟点击一次多少钱
  • 昆明建网站公司百度seo优化及推广
  • 电子商务概论亿唐网不做网站做品牌想建立自己的网站怎么建立
  • 手机网站建设软件下载网站seo优化是什么意思
  • 网站和管理系统哪个更难做网站设计说明
  • 百度文库怎么做网站排名北京seo网络优化招聘网
  • 做网站的是什么专业整合营销传播策划方案
  • 这么给网站做关键字网络推广方案模板
  • 如何建立免费的网站游戏推广怎么做挣钱
  • 政府网站建设培训通知知识付费网站搭建
  • 企业网站建设商城哪个网站是免费的
  • 没得公司可以做网站嘛aso搜索优化
  • 长沙做网站需要多少钱竞价广告是怎么推广的
  • 深圳网站建设培训线上推广方式都有哪些
  • 网站模板的功能网络推广好做吗多少钱
  • 在线音乐网站开发现状2023年最新新闻摘抄
  • 18款禁用网站app破解版少儿编程
  • 网站ui界面设计最佳磁力吧cili8
  • wp做网站需要多久网络销售员每天做什么
  • 东莞网站建设案例百度指数名词解释
  • 日照莒县网站建设公司企业邮箱域名
  • 杭州微信网站制作长沙seo招聘
  • 成都网站seo公司网络推广公司电话
  • 在百度做推广需要网站吗电子商务网站建设方案