您的位置:首页 > 房产 > 建筑 > 乐清网站制作的公司_易趣网的网站架构_最热门的短期培训课程_网络营销工具的特点

乐清网站制作的公司_易趣网的网站架构_最热门的短期培训课程_网络营销工具的特点

2025/4/22 4:30:06 来源:https://blog.csdn.net/jiyanghao19/article/details/139609589  浏览:    关键词:乐清网站制作的公司_易趣网的网站架构_最热门的短期培训课程_网络营销工具的特点
乐清网站制作的公司_易趣网的网站架构_最热门的短期培训课程_网络营销工具的特点

文章目录

  • 概述
  • 13.1拷贝、赋值与销毁
    • 合成拷贝构造函数
    • 拷贝初始化
    • 参数和返回值
    • 拷贝初始化的限制
    • 编译器可以绕过拷贝构造函数
    • 拷贝运算符
    • 析构函数
    • 三/五原则
      • 使用=default
      • 阻止拷贝
      • 合成的拷贝控制成员可能是删除的
    • private拷贝控制
    • 拷贝控制和资源管理
      • 行为像值的类
      • 类值拷贝赋值运算符
      • 定义行为像指针的类
      • 引用计数
      • 定义一个引用计数的类
      • 类指针的拷贝成员“篡改” 引用计数
  • 交换操作
  • 拷贝控制示例
  • 动态内存管理
  • 对象移动
    • 右值引用
    • 移动构造函数和移动赋值运算符
    • 移动迭代器

概述

在这里插入图片描述

13.1拷贝、赋值与销毁

在这里插入图片描述

合成拷贝构造函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

拷贝初始化

在这里插入图片描述
在这里插入图片描述

参数和返回值

在这里插入图片描述

拷贝初始化的限制

在这里插入图片描述

编译器可以绕过拷贝构造函数

在这里插入图片描述

拷贝运算符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

析构函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三/五原则

在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

使用=default

在这里插入图片描述

阻止拷贝

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述### 析构函数不能是删除成员

在这里插入图片描述

合成的拷贝控制成员可能是删除的

在这里插入图片描述
在这里插入图片描述

private拷贝控制

在新标准发布之前 ,类是通过将其拷贝构造函数和拷贝赋值运算符芦明为 pr ivate
的来阻止拷贝:

class Priva teCopy {
//元访问说明符 ;接下来的成员默认为p rivate 的;参见 7.2 节 ( 第 240 页 )
//拷贝控制成员是 priv a te 的,因此普通用户代码无法访问
Priva teCopy ( const Priva teCopy& ) ;
PrivateCopy & operator= ( const Priva teCopy& ) ;
//其他成员
public :
Pr ivateCopy ( ) = def au lt ; //使用合成的默认构造函数
~PrivateCopy ( ) ; // 用尸可以定义此类型的对象 ,但无法拷贝它们

由于析构函数是 public 的,用户可以定义 Pr ivateCopy 类型的对象 。但是 ,由于拷贝 构造函数和拷贝赋值运算符是 pr iva te 的,用户代码将不能拷贝这个类型的对象
。但是, 友元和成员函数仍旧可以拷贝对象 。为了阻止友元和成员函数进行拷贝,我们将这些拷贝 控制成员声明为 pr iva t e 的,但并不定义它们 。
声明但不定义 个成员函数是合法的 ( 参见 6. 1.2 节,第 186 页),对此只有一个例外 , 我们将在 15.2.1 节 (第 528 页) 中介绍。试图访问一个未定义的成员将导致
一个链接时错 误。通过声明 (但不定义) pr ivate 的拷贝构造函数 ,我们可以预先阻止任何拷贝该类 型对象的企图 :试图拷贝对象的用户代码将在编译阶段被标记为错 误:成员函数或友元函
数中的拷贝操作将会导致链接时错误 。
在这里插入图片描述

拷贝控制和资源管理

在这里插入图片描述

行为像值的类

在这里插入图片描述
在这里插入图片描述

类值拷贝赋值运算符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

定义行为像指针的类

在这里插入图片描述

引用计数

在这里插入图片描述

定义一个引用计数的类

在这里插入图片描述
在这里插入图片描述

类指针的拷贝成员“篡改” 引用计数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

交换操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

拷贝控制示例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

动态内存管理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对象移动

在这里插入图片描述
在这里插入图片描述

右值引用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

移动构造函数和移动赋值运算符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#pragma once
#include <iostream>
class HasPtr
{friend void swap(HasPtr&, HasPtr&);
public://默认构造函数HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0){}//拷贝构造函数HasPtr(const HasPtr& data) : ps(new std::string(*(data.ps))), i(data.i){}//添加都移动构造函数HasPtr(HasPtr&& P)noexcept :ps(P.ps), i(P.i) {P.ps = nullptr;P.i = 0;}HasPtr& operator=(HasPtr rhs){swap(*this, rhs);return *this;}// 析构函数~HasPtr(){delete ps;}
private:std::string* ps;int i;
};inline void swap(HasPtr& lhs, HasPtr& rhs)
{using std::swap;swap(lhs.ps, rhs.ps); // swap the pointers, not the string dataswap(lhs.i, rhs.i); // swap the int members
}
int main()
{HasPtr data1, data2("123"), data3, data4("abc");data1 = data2;//拷贝语义data3 = std::move(data4);//移动语义
}

所有五个拷贝控制成员应该看作一个整体:一般来说,如果一个类定义了任何一个拷贝操作,它应该定义所有五个操作。如前所述,某些类必须定义拷贝构造函数、拷贝赋值运算符和析构函数。这些类只有一个资源,而拷贝成员必须拷贝此资源。

移动迭代器

#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <algorithm>
#include <cassert>class StrVec {
public:// 默认构造函数StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {std::cout << "Default constructor called." << std::endl;}// 拷贝构造函数StrVec(const StrVec& s) {std::cout << "Copy constructor called." << std::endl;auto newdata = alloc_n_copy(s.begin(), s.end());elements = newdata.first;first_free = cap = newdata.second;}// 移动构造函数StrVec(StrVec&& s) noexcept : elements(s.elements), first_free(s.first_free), cap(s.cap) {std::cout << "Move constructor called." << std::endl;s.elements = s.first_free = s.cap = nullptr;}// 拷贝赋值运算符StrVec& operator=(const StrVec& rhs) {std::cout << "Copy assignment operator called." << std::endl;auto data = alloc_n_copy(rhs.begin(), rhs.end());free();elements = data.first;first_free = cap = data.second;return *this;}// 移动赋值运算符StrVec& operator=(StrVec&& rhs) noexcept {std::cout << "Move assignment operator called." << std::endl;if (this != &rhs) {free();elements = rhs.elements;first_free = rhs.first_free;cap = rhs.cap;rhs.elements = rhs.first_free = rhs.cap = nullptr;}return *this;}// 析构函数~StrVec() {std::cout << "Destructor called." << std::endl;free();}// 拷贝版本的 push_backvoid push_back(const std::string& s) {std::cout << "Copy push_back called with: " << s << std::endl;chk_n_alloc();alloc.construct(first_free++, s);}// 移动版本的 push_backvoid push_back(std::string&& s) {std::cout << "Move push_back called with: " << s << std::endl;chk_n_alloc();alloc.construct(first_free++, std::move(s));}// 返回元素数量size_t size() const { return first_free - elements; }// 返回容量size_t capacity() const { return cap - elements; }// 返回起始迭代器std::string* begin() const { return elements; }// 返回结束迭代器std::string* end() const { return first_free; }// 左值版本的 sorted 方法void sorted() & {std::cout << "Lvalue sorted called." << std::endl;std::sort(begin(), end());}// 右值版本的 sorted 方法StrVec sorted() && {std::cout << "Rvalue sorted called." << std::endl;std::sort(begin(), end());return std::move(*this);}private:std::allocator<std::string> alloc;// 检查是否需要重新分配内存void chk_n_alloc() {if (size() == capacity()) {reallocate();}}// 分配并复制元素std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);// 释放内存void free();// 重新分配内存void reallocate();std::string* elements;std::string* first_free;std::string* cap;
};// 分配并复制元素的实现
std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string* b, const std::string* e) {auto data = alloc.allocate(e - b);return {data, std::uninitialized_copy(b, e, data)};
}// 释放内存的实现
void StrVec::free() {if (elements) {for (auto p = first_free; p != elements; ) {alloc.destroy(--p);}alloc.deallocate(elements, cap - elements);}
}// 重新分配内存的实现
void StrVec::reallocate() {std::cout << "Reallocating memory..." << std::endl;auto newcapacity = size() ? 2 * size() : 1;auto newdata = alloc.allocate(newcapacity);auto dest = newdata;auto elem = elements;for (size_t i = 0; i != size(); ++i) {alloc.construct(dest++, std::move(*elem++));}free();elements = newdata;first_free = dest;cap = elements + newcapacity;
}// 打印 StrVec 中的元素
void printStrVec(const StrVec& vec) {for (auto it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;
}// 测试默认构造函数
void testDefaultConstructor() {StrVec vec;assert(vec.size() == 0);std::cout << "Default constructor test passed." << std::endl;
}// 测试拷贝构造函数
void testCopyConstructor() {StrVec vec1;vec1.push_back("apple");vec1.push_back("banana");StrVec vec2(vec1);assert(vec2.size() == vec1.size());auto it1 = vec1.begin();auto it2 = vec2.begin();while (it1 != vec1.end() && it2 != vec2.end()) {assert(*it1 == *it2);++it1;++it2;}std::cout << "Copy constructor test passed." << std::endl;
}// 测试移动构造函数
void testMoveConstructor() {StrVec vec1;vec1.push_back("cherry");vec1.push_back("date");StrVec vec2(std::move(vec1));assert(vec1.size() == 0);assert(vec2.size() == 2);std::cout << "Move constructor test passed." << std::endl;
}// 测试拷贝赋值运算符
void testCopyAssignmentOperator() {StrVec vec1;vec1.push_back("elderberry");vec1.push_back("fig");StrVec vec2;vec2 = vec1;assert(vec2.size() == vec1.size());auto it1 = vec1.begin();auto it2 = vec2.begin();while (it1 != vec1.end() && it2 != vec2.end()) {assert(*it1 == *it2);++it1;++it2;}std::cout << "Copy assignment operator test passed." << std::endl;
}// 测试移动赋值运算符
void testMoveAssignmentOperator() {StrVec vec1;vec1.push_back("grape");vec1.push_back("honeydew");StrVec vec2;vec2 = std::move(vec1);assert(vec1.size() == 0);assert(vec2.size() == 2);std::cout << "Move assignment operator test passed." << std::endl;
}// 测试 push_back 方法
void testPushBack() {StrVec vec;vec.push_back("apple");vec.push_back(std::string("banana"));assert(vec.size() == 2);std::cout << "Push_back test passed." << std::endl;
}// 测试 sorted 方法(左值)
void testSortedLvalue() {StrVec vec;vec.push_back("banana");vec.push_back("apple");vec.push_back("cherry");vec.sorted();auto it = vec.begin();assert(*it == "apple");++it;assert(*it == "banana");++it;assert(*it == "cherry");std::cout << "Sorted (lvalue) test passed." << std::endl;
}// 测试 sorted 方法(右值)
void testSortedRvalue() {StrVec sortedVec = StrVec().push_back("grape").push_back("date").push_back("elderberry").sorted();auto it = sortedVec.begin();assert(*it == "date");++it;assert(*it == "elderberry");++it;assert(*it == "grape");std::cout << "Sorted (rvalue) test passed." << std::endl;
}int main() {testDefaultConstructor();testCopyConstructor();testMoveConstructor();testCopyAssignmentOperator();testMoveAssignmentOperator();testPushBack();testSortedLvalue();testSortedRvalue();std::cout << "All tests passed!" << std::endl;return 0;
}    
}    

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com