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

邯郸做移动网站价格表网页设计尺寸1440

邯郸做移动网站价格表,网页设计尺寸1440,html网站模板怎么用,厦门市住房和城乡建设局网站首页移动语义 目录 右值引用变量是左值move库函数移动构造函数和移动赋值移动操作库容器和异常移动赋值操作符移动后的对象必须是可以析构的合成移动操作右值移动左值拷贝右值在无法被移动时进行拷贝拷贝和交换赋值操作与移动移动迭代器右值引用和成员函数右值与左值引用的成员函…移动语义 目录 右值引用变量是左值move库函数移动构造函数和移动赋值移动操作库容器和异常移动赋值操作符移动后的对象必须是可以析构的合成移动操作右值移动左值拷贝右值在无法被移动时进行拷贝拷贝和交换赋值操作与移动移动迭代器右值引用和成员函数右值与左值引用的成员函数重载带引用修饰符的成员函数精确传递 关键术语 有一些类的资源是__不可共享__的这种类型的对象可以被移动但不能被拷贝如IO 或 unique_ptr 库容器、string 和 shared_ptr 支持拷贝和移动IO 和 unique_ptr 则只能移动不能拷贝。。 右值引用 右值引用是必须绑定到右值的引用右值引用使用 符号相较于左值引用的 。右值引用有一个特性就是其只能绑定到即将销毁的对象上因而可以自由的移动右值引用对象中的资源。 左值表示对象的身份而右值表示对象的值。不能将左值引用(lvalue reference)绑定到需要转型的值、字面量或者返回右值的表达式上。右值引用则刚好相反可以将右值引用绑定到以上的值但不能直接将右值引用绑定到左值。如 int i 42; int r i; int rr i; //错误不能将右值引用绑定到左值上 int r2 i * 42; //错误不能将左值引用绑定到右值上 const int r3 i * 42; //可以将 const 左值引用绑定到任何类型的值上const/非 const 的左/右值 int rr2 i * 42; //将右值引用绑定到右值上返回左值引用的函数和赋值、下标操作、解引用和前缀自增/自减操作符都是返回左值的表达式可将左值引用绑定到这些表达式的结果中。 返回非引用类型的函数与算术、关系、位操作和后缀自增/自减的操作符都是返回右值的表达式可将右值引用和 const 左值引用绑定到这种表达式上。 变量是左值 一个变量就是一个表达式其只有一个操作数而没有操作符。变量表达式是左值。因而不能将右值引用绑定到一个定义为右值引用的变量上。如 int rr1 42; int rr2 rr1; //错误rr1 是左值因而不能这样定义一个变量就是一个左值不能直接将右值引用绑定到一个变量上即使这个变量被定义为右值引用类型也不可以。 但是如果临时对象通过一个接受右值的函数传递给另一个函数时就会变成左值因为这个临时对象在传递过程中变成了命名对象。 move库函数 template class T (C11 起) typename std::remove_referenceT::type move( T t ) noexcept; (C14 前)template class T (C14 起) constexpr typename std::remove_referenceT::type move( T t ) noexcept;可以显式将左值强转为对应的右值引用类型也可以通过调用 move 库函数来获取绑定到左值的右值引用其被定义在 utility 头文件中。如 int rr3 std::move(rr1);调用 move 告知编译器以右值方式对象一个左值。特别需要了解的是调用 move 将承诺不会再次使用 rr1 除非是赋值或者析构。当调用了 move 之后不能对这个对象做任何值上的假设。可以析构或赋值给移动后的对象但在此之前不能使用其值。 使用 move 的代码应该使用 std::move 而不是 move这样做可以避免潜在的名字冲突。 移动构造函数和移动赋值 为了让我们自己的类可以执行移动操作需要定义移动构造函数和移动赋值操作符。这些成员类似于对应的拷贝赋值操作但是他们将从给定对象中偷取资源而不是复制。 参数右值不可以是常量因为我们需要修改右值。参数右值的资源链接和标记必须修改。否则右值的析构函数就会释放资源。转移到新对象的资源也就无效了。 除了移动资源移动构造函数需要保证移动后的对象的状态是析构无害的。特别是一旦资源被移动后原始对象就不再指向移动了的资源这些所有权被转移给了新创建的对象。如 StrVec::StrVec(StrVec s) noexcept :elements(s.elements), first_free(s.first_free), cap(s.cap) {s.elements s.first_free s.cap nullptr; }与拷贝构造函数不同移动构造函数并不会分配新资源其将攫取参数中的内存在此之后构造函数体将参数中的指针都设置为 nullptr当一个对象被移动后这个对象依然存在。最后移动后的对象将被析构意味着析构函数将在此对象上运行。析构函数将释放其所拥有的资源如果没有将指针设置为 nullptr 的就会将移动了的资源给释放掉。 移动操作库容器和异常 移动操作通常不必自己分配资源所以移动操作通常不抛出任何异常。当我们写移动操作时由于其不会抛出异常我们应当告知编译器这个事实。除非编译器知道这个事实它将必须做额外的工作来满足移动构造操作将抛出异常。 通过在函数参数列表后加上 noexcept 在构造函数时则noexcept 出现在参数列表后到冒号之间来告知编译器一个函数不会抛出异常。如 class StrVec { public:StrVec(StrVec ) noexcept; }; StrVec::StrVec(StrVec s) noexcept : { ... }必须同时在类体内的声明处和定义处同时指定 noexcept。 移动构造函数和移动赋值操作符如果都不允许抛出异常那么就应该被指定为 noexcept。 告知移动操作不抛出异常是由于两个不相关的事实第一尽管移动操作通常不抛出异常它们可以这样做。第二有些库容器在元素是否会在构建时抛出异常有不同的表现如vector 只有在知道元素类型的移动构造函数不会抛出异常才使用移动构造函数否则将必须使用拷贝构造函数 移动赋值操作符 StrVec StrVec::operator(StrVec rhs) noexcept {if (this rhs)return *this;free();elements rhs.elements;first_free rhs.first_free;cap rhs.cap;rhs.elements rhs.first_free rhs.cap nullptr;return *this; }* 移动赋值操作符不抛出异常应当用 noexcept 修饰与拷贝赋值操作符一样需要警惕自赋值的可能性。移动赋值操作符同时聚合了析构函数和移动构造函数的工作其将释放左操作数的内存并且占有右操作数的内存并将右操作数的指针设为 nullptr。 移动后的对象必须是可以析构的 移动对象并不会析构那个对象有时在移动操作完成后被移动的对象将被销毁。因而当我们写移动操作时必须保证移动后的对象的状态是可以析构的。StrVec 通过将其指针设置为 nullptr 来满足此要求。 除了让对象处于可析构状态移动操作必须保证对象处于有效状态。通常来说有效状态就是可以安全的赋予新值或者使用在不依赖当前值的方式下。另一方面移动操作对于遗留在移动后的对象中的值没有什么特别要求所以程序不应该依赖于移动后对象的值。 例如从库 string 和容器对象中移动资源后移动后对象的状态将保持有效。可以在移动后对象上调用 empty 或 size 函数然而并不保证得到的结果是空的。可以期望一个移动后对象是空的但是这并不保证。 以上 StrVec 的移动操作将移动后对象留在一个与默认初始化一样的状态。因而这个 StrVec 的所有操作将与默认初始化的 StrVec 的操作完全一样。其它类有着更加复杂的内部结构也许会表现的不一致。 在移动后操作移动后对象必须保证在一个有效状态并且可以析构但是用户不能对其值做任何假设。 合成移动操作 编译器会为对象合成移动构造函数和移动赋值操作符。然而在什么情况下合成移动操作与合成拷贝操作是十分不同的。 与拷贝操作不同的对于某些类来说编译器根本不合成任何移动操作。特别是如果一个类定义自己的拷贝构造函数、拷贝赋值操作符或析构函数移动构造函数和移动赋值操作符是不会合成的。作为结果有些类是没有移动构造函数或移动赋值操作符。同样当一个类没有移动操作时对应的拷贝操作将通过函数匹配被用于替代移动操作。 编译器只会在类没有定义任何拷贝控制成员并且所有的非 static 数据成员都是可移动的情况下才会合成移动构造函数和移动赋值操作符。编译器可以移动内置类型的成员亦可以移动具有对应移动操作的类类型成员。 移动操作不会隐式被定义为删除的而是根本不定义当没有移动构造函数时重载将选择拷贝构造函数。当用 default 要求编译器生成时如果编译器无法移动所有成员将会生成一个删除的移动操作。被删除的函数不是说不能被用于函数重载而是说当其是重载解析时最合适的候选函数时将是编译错误。 与拷贝构造函数不同当类有一个成员定义了自己的拷贝构造函数但是没有定义移动构造函数时使用拷贝构造函数。当成员没有定义自己的拷贝操作但是编译器无法为其合成移动构造函数时其移动构造函数被定义为被删除的。对于移动赋值操作符是一样的如果类有一个成员其移动构造函数或移动赋值操作符是被删除的或不可访问的其移动构造函数或移动赋值操作符被定义为被删除的与拷贝构造函数一样如果其析构函数是被删除的或不可访问的移动构造函数被定义为被删除的与拷贝赋值操作符一样如果其有一个 const 或引用成员移动赋值操作被定义为删除的 如果一个类定义自己的移动构造函数或移动赋值操作符那么合成的拷贝构造函数和拷贝赋值操作符都将被定义为被删除的。 右值移动左值拷贝 当一个类既有移动构造函数又有拷贝构造函数编译器使用常规的函数匹配来决定使用哪个构造函数。拷贝构造函数通常使用 const StrVec 引用类型作为参数因而可以匹配可以转为 StrVec 类型的对象参数。而移动构造函数则使用 StrVec 作为参数因而只能使用非 const 的右值。如果调用拷贝形式的需要将参数转为 const 的而移动形式的却是精确匹配因而右值将调用移动形式的。 右值在无法被移动时进行拷贝 如果一个类有拷贝构造函数但是没有定义移动构造函数在这种情况下编译不会合成移动构造函数意味着类只有拷贝构造函数而没有移动构造函数。如果一个类没有移动构造函数函数匹配保证即便是尝试使用 move 来移动对象时它们依然会被拷贝。 class Foo { public:Foo() default;Foo(const Foo); //拷贝构造函数 }; Foo x; Foo y(x); //拷贝构造函数x 是左值 Foo z(std::move(x)); //拷贝构造函数因为没有移动构造函数调用 move(x) 时返回 Foo Foo 的拷贝构造函数是可行的因为可以将 Foo 转为 const Foo 因而使用拷贝构造函数来初始化 z 。 使用拷贝构造函数来替换移动构造函数通常是安全的对于赋值操作符来说是一样的。拷贝构造符合移动构造函数的先决条件它将拷贝给定的对象并且不会改变其状态这样原始对象将保持在有效状态内。 拷贝和交换赋值操作与移动 class HasPtr { public:HasPtr(HasPtr p) noexcept : ps(p.ps), i(p.i) {p.ps 0;}HasPtr operator(HasPtr rhs){swap(*this, rhs);return *this;} };* 赋值操作符的参数是非引用类型的所以参数是拷贝初始化的。根据参数的类型拷贝初始化可能使用拷贝构造函数也可能使用移动构造函数。左值将被拷贝右值将被移动。因而这个移动操作符既是拷贝赋值操作符又是移动赋值操作符。如 hp hp2; hp std::move(hp2);所有五个拷贝控制成员应该被当做一个整体通常如果一个类定义了其中任何一个操作它通常需要定义所有成员。有些类必须定义拷贝构造函数拷贝赋值操作符和析构函数才能正确工作。这种类通常有一个资源是拷贝成员必须拷贝的通常拷贝资源需要做很多额外的工作定义移动构造函数和移动赋值操作符可以避免在不需要拷贝的情况的额外工作。 移动迭代器 在新标准中定义了移动迭代器(move iterator)适配器。移动迭代器通过改变迭代器的解引用操作来适配给定的迭代器。通常迭代器解引用返回元素的左值引用与其它迭代器不同解引用移动迭代器返回右值引用。调用函数 make_move_iterator 将常规迭代器变成移动迭代器移动迭代器的操作与原始迭代器操作基本一样因而可以将移动迭代器传给 uninitialized_copy 函数。如 uninitialized_copy(make_move_iterator(begin()), make_move_iterator(end()));值得一提的是标准库没有说哪些算法可以使用移动迭代器哪些不可以。因为移动对象会破坏原始对象所以将移动迭代器传给那些不会在移动后访问其值的算法才合适。 慎用移动操作由于移动后的对象处于中间状态在对象上调用 std::move 是很危险的。当调用 move 后必须保证没有别的用户使用移动后对象。 谨慎克制的在类内使用 move 可以提供重大的性能提升在用户代码中使用 move 则更可能导致难以定位的 bug相比较得到的性能提升是不值得的。 在类实现代码外使用 std::move必须是在确实需要移动操作并且保证移动是安全的。 右值引用和成员函数 除了构造函数和赋值操作符外提供拷贝和移动版本亦会受益。这种可以移动的成员函数中一个使用 const 左值引用另一个使用非 const 右值引用。如 void push_back(const X); //拷贝绑定到任何类型的 X void push_back(X); //移动绑定到可修改的右值 X可以传递任何可以转换为类型 X 的对象给拷贝版本这个版本从参数中拷贝数据。只能将非 const 右值传递给移动版本。此版本比拷贝版本更好的匹配非 const 右值精确匹配因而在函数匹配中将是更优的并且可以自由的从参数中移动资源。 通常上面这种重载方式不会使用 const X 和 X 类型的参数原因在于移动数据要求对象是非 const 的而拷贝数据则应该是 const 的。 以拷贝或移动的方式对函数进行重载常用的做法是一个版本使用 const T 为参数另外一个版本使用 T 为参数。 右值与左值引用的成员函数 有些成员函数是只允许左值调用的右值是不能调用的如在新标准前可以给两个字符串拼接的结果赋值s1 s2 wow!; 在新标准中可以强制要求赋值操作符的左操作数是左值通过在参数列表后放置引用修饰符(reference qualifier)可以指示 this 的左值/右值特性。如 class Foo { public:Foo operator(const Foo) ; }; Foo Foo::operator(const Foo rhs) { return *this; }* 引用修饰符可以是 或者 用于表示 this 指向左值或右值。与 const 修饰符一样引用修饰符必须出现在非 static 成员函数的声明和定义处。被 修饰的函数只能被左值调用被 修饰的函数只能被右值调用。 一个函数既可以有 const 也可以有引用修饰符在这种情况下引用修饰符在 const 修复符的后面。如 class Foo { public:Foo someMem() const ; };重载带引用修饰符的成员函数 可以通过函数的引用修饰符进行重载这与常规的函数重载是一样的 可以在可修改的右值上调用const 可以在任何类型的对象上调用。如 class Foo { public:Foo sorted() ; //可以在可修改的右值上调用Foo sorted() const ; //可以在任何类型的 Foo 上调用 };当定义具有相同名字和相同参数列表的成员函数时必须同时提供引用修饰符或者都不提供引用修饰符如果只在其中一些提供而另外一些不提供就是编译错误。如 class Foo { public:Foo sorted() ;Foo sorted() const; //错误必须提供引用修饰符//全不提供引用修饰符是合法的using Comp bool(const int, const int);Foo sorted(Comp*);Foo sorted(Comp*) const; };精确传递 本文采用精确传递(Perfect Forwarding)表达这个意思。Perfect Forwarding也被翻译成完美转发精准转发等说的都是一个意思。 精确传递适用于这样的场景需要将一组参数原封不动的传递给另一个函数。 “原封不动”不仅仅是参数的值不变在 C 中除了参数值之外还有一下两组属性 左值右值和 const/non-const。 精确传递就是在参数传递过程中所有这些属性和参数值都不能改变。在泛型函数中这样的需求非常普遍。 下面举例说明。函数 forward_value 是一个泛型函数它将一个参数传递给另一个函数 process_value。 forward_value 的定义为 template typename T void forward_value(const T val) {process_value(val); } template typename T void forward_value(T val) {process_value(val); }函数 forward_value 为每一个参数必须重载两种类型T 和 const T否则下面四种不同类型参数的调用中就不能同时满足 : int a 0;const int b 1;forward_value(a); // intforward_value(b); // const int forward_value(2); // int对于一个参数就要重载两次也就是函数重载的次数和参数的个数是一个正比的关系。这个函数的定义次数对于程序员来说是非常低效的。我们看看右值引用如何帮助我们解决这个问题 : template typename T void forward_value(T val) {process_value(val); }只需要定义一次接受一个右值引用的参数就能够将所有的参数类型原封不动的传递给目标函数。四种不用类型参数的调用都能满足参数的左右值属性和 const/non-cosnt属性完全传递给目标函数 process_value。这个解决方案不是简洁优雅吗 int a 0; const int b 1; forward_value(a); // int forward_value(b); // const int forward_value(2); // intC11 中定义的 T 的推导规则为 右值实参为右值引用左值实参仍然为左值引用。 一句话就是参数的属性不变。这样也就完美的实现了参数的完整传递。 右值引用表面上看只是增加了一个引用符号但它对 C 软件设计和类库的设计有非常大的影响。它既能简化代码又能提高程序运行效率。每一个 C 软件设计师和程序员都应该理解并能够应用它。我们在设计类的时候如果有动态申请的资源也应该设计转移构造函数和转移拷贝函数。在设计类库时还应该考虑 std::move 的使用场景并积极使用它。 关键术语 拷贝-交换(copy and swap)一种书写赋值操作符的技术先将右操作数拷贝到参数中然后调用 swap 将其与左操作数进行交换 拷贝赋值操作符(copy-assignment operator)拷贝赋值操作符与本类的 const 引用对象作为参数返回对象的引用。如果类不定义拷贝赋值操作符编译器将合成一个 拷贝构造函数(copy constructor)将新对象初始化为本类的另一个对象的副本的构造函数。拷贝构造函数将在以非引用方式传递参数或从函数中返回时默认调用。如果类不定义的话编译器将合成一个 拷贝控制(copy control)用于控制对象被拷贝、移动、赋值和销毁时应当做什么的成员函数。如果类不定这些函数编译器将在合适的时候合成它们 拷贝初始化(copy initialization)使用 形式的初始化或者当传递参数、按值形式返回值或者初始化数组或聚合类时将进行拷贝初始化。拷贝初始化将根据初始值是左值还是右值使用拷贝构造函数或者移动构造函数 被删除的函数(deleted function)不被使用的函数通过 delete 来删除函数。使用被删除的函数是告知编译器在进行函数匹配时如果匹配到被删除的函数就报编译器错误 析构函数(destructor)当对象离开作用域时调用的特殊成员函数来清理对象。编译器自动销毁每个数据成员类成员通过调用其析构函数进行销毁内置类型或符合类型将不做任何析构操作特别是指向动态对象的指针不会被自动 delete 逐个成员拷贝/赋值(memberwise copy/assign)合成的拷贝/移动构造函数和拷贝/移动赋值操作符的运作方式。依次对所有的数据成员拷贝/移动构造函数通过从参数中拷贝/移动对应的成员进行初始化拷贝/移动赋值操作符则依次对右操作数的各个成员进行拷贝/移动赋值内置类型的成员是直接进行初始化或赋值的。类类型成员则调用对应的拷贝/移动构造函数或拷贝/移动赋值操作符 move 函数(move function)用于将左值绑定到右值引用的库函数。调用 move 将隐式保证不会使用移动后的对象值唯一的操作是析构或者赋予新值 移动赋值操作符(move-assignment operator)参数是右值引用的赋值操作符版本。通常移动赋值操作符将其右操作数的数据移动到左操作数。在赋值后必须保证可以安全的析构掉右操作数 移动构造函数(move constructor)以右值引用为参数的构造函数。移动构造函数将参数中的数据移动到新创建的对象中。在移动后必须保证可以安全地析构掉右操作数 移动迭代器(move iterator)迭代器适配器包装一个迭代器当其解引用时返回右值引用 右值引用(rvalue reference)对即将被销毁的对象的引用 我的github地址
http://wiki.neutronadmin.com/news/116643/

相关文章:

  • 定制app网站wordpress备份如何恢复
  • 网站怎么做自然优化哪个厂家的logo品牌设计
  • 郑州市二七建设局网站网站上的动态背景怎么做的
  • 鞋材加工东莞网站建设企业网站建设收费
  • 做网站的市场风险分析及对策汕头app开发
  • 网络营销工具体系深圳白帽优化
  • 吉他谱网站如何建设域名注册要多少钱
  • 网站推广的10种方法新加坡服务器网站需要备案么
  • 巩义网站建设方式优化购物网站配色怎么设计
  • 我是做网站怎么赚钱做付费网站
  • 程序源代码网站移动端网站建设公司
  • 微信网站打不开html做的网页怎么变成网站
  • 中职网站建设与管理网站改版建设公司
  • 哪家微网站做的好公司免费网站注册
  • 太原做手机网站设计网页设计培训平台
  • 网站广告图怎么做wordpress固定链接是存在哪个表
  • dede网站模板怎么改苏州注册公司一站式
  • 义乌制作网站开发seo基础篇
  • 买网站自己做做淘客的网站有哪些
  • 个人网站备案做商城做的好看的国内网站欣赏
  • 怎么去营销自己的产品惠州市seo广告优化营销工具
  • 做表格的网站做网站违法吗
  • 柳州门户网站建设公司排名google移动服务应用优化
  • 网站设计制做报价自建app免费制作平台
  • 怎么做公众号网站吗微商建立网站
  • 网站配图尺寸wordpress自适应空白主题
  • 大庆免费网站建设动态图片在线制作
  • 建设企业网站的好处wordpress汉化版
  • 网站建站的流程wordpress 分享到微信
  • 网站开发加22760047安徽伟诚建设工程有限公司网站