C++并发编程实战第6章问题

[读书笔记]C++并发编程实战 [读书笔记]C++并发编程实战 原文地址:https://github.com/xuyicpp/multi_threading C++并发编程的内容每一章都从浅入深讲解的很详细,虽然第一遍有一些还不是很懂,例如无锁编程和线程池,以后遇到这些问题可以回来翻翻笔记加深印象。 multi_threading 《C++并发编程实战》的读书笔记,供以后工作中查阅。 第一章 何谓并发和多线程... 阅读详情

C++并发编程实战第6章,代码清单6.4队列实现——单线程版

template<typename T>
class queue
{
private:
  struct node
  {
    T data;
    std::unique_ptr<node> next;

    node(T data_):
    data(std::move(data_))
    {}
  };

  std::unique_ptr<node> head;  // 1
  node* tail;  // 2

public:
  queue()
  {}
  queue(const queue& other)=delete;
  queue& operator=(const queue& other)=delete;
  std::shared_ptr<T> try_pop()
  {
    if(!head)
    {
      return std::shared_ptr<T>();
    }
    std::shared_ptr<T> const res(
      std::make_shared<T>(std::move(head->data)));
    std::unique_ptr<node> const old_head=std::move(head);
    head=std::move(old_head->next);  // 3
    return res;
  }

  void push(T new_value)
  {
    std::unique_ptr<node> p(new node(std::move(new_value)));
    node* const new_tail=p.get();
    if(tail)
    {
      tail->next=std::move(p);  // 4
    }
    else
    {
      head=std::move(p);  // 5
    }
    tail=new_tail;  // 6
  }
};

首先,定义数据结构时,head为unique_ptr,tail为原生指针,而不是使用两个unique_ptr,此处意在避免对同一非nullptr地址的两次delete,因为智能指针的默认deleter(std::default_delete)在delete堆后并不会将指针置nullptr,这个没什么问题,大家看的时候可能有疑惑,提出来一下

然后,queue为构造函数函数体为空,配合原生指针类型的tail,显而易见的野指针(当在栈上使用queue时)

最后在try_pop中并没有考虑这样一种情况,当head指向最后一个节点,此时try_pop,tail将指向不合法位置

C++并发编程 第1章:C++的并发世界 1.1 何谓并发 最简单和最基本的并发,是指两个或更多独立的活动同时发生。 并发在生活中随处可见,我们可以一边走路一边说话,也可以两只手同时作不同的动作,还有我们每个人都过着相互独立的生活——当我在游泳的时候,你可以看球赛,等等。 1.1.1 计算机系统中的并发 计算机领域的并发指的是在单个系统里同时执行多个独立的任务,而非顺序的进行一些活动。 计算机领域里,并发不是一个新事物:很多年前,一台计算机就能通过多任务操作系统的切换功能,同时运行多个应用程序;高端多处理器服务 阅读详情

相关推荐

C++ Concurrency in Action, 2nd Edition C++ 并发编程实战 第二版 note part 1

复制数据返回给调用者可能会抛出异常,被pop出来的值只有在栈完成修改以后才会返回给调用者,所以栈首先删除了这个值,然后这个值才被复制并返回。此时复制时抛出异常,就导致了刚刚pop掉的值丢失了,而且已经被栈删除了。std::stack操作的设计者将这个操作分成了两个:获取栈顶的值top,从栈内删除这个值pop。若你不能安全的复制这个值,那么它还在栈内。当然若只是缺少堆内存,释放内存就可以了。从上面的讲述可以发现:某些组合起来的操作,需要分开才行。

邹九的个人博客 1951

C++ 并发编程实战 第六章 设计基于锁的并发数据结构

多线程环境下,无数据丢失和损毁,所有的数据需要维持原样,且无条件竞争的数据结构,称之为“线程安全”的数据结构。当线程执行不同的操作时,对同一数据结构的并发操作是安全的,而多线程执行同样的操作时,可能会出现问题。这种情况不可以,所以调用函数需要改成data_cond.notify_all(),这个函数将唤醒所有的工作线程,不过当大多线程发现队列依旧是空时,又会耗费资源让线程重新进入睡眠。虽然,有些数据结构比其他结构的并发访问范围更大,但思路都是一样的:减少保护区域,减少序列化操作,提升并发访问的能力。

qq_52758467的博客 483

在Window上安装和配置VTK9.x,并在QT项目中调试VTK是否可用

VTK+MSVC+Qt Creator + CMake配置

qq_42279379的博客 1000

《C++并发编程实战》笔记-第6章设计基于锁的并发数据结构

基于锁的并发数据结构

qq_42692132的博客 206

超详细的YOLOv8安装与测试指南:让计算机视觉任务变得简单

python3+、Anaconda3或Miniconda3 Ultralytics提供了多种安装方法,包括pip、conda和Docker。通过pip包安装最新稳定版的YOLOv8,或者克隆Ultralytics GitHub仓库以获取最新版本。Docker可用于在隔离容器中执行包,避免本地安装。 最简单直接的方式就是直接使用pip方法直接安装。 也可以直接从GitHub仓库安装包。如果你想要最新的开发版本,这可能会很有用。确保你的系统上安装了Git命令行工具

CDBmax的博客 1万+

PLS-PM with R 偏最小二乘路径建模 (R语言)

1. 引入 1.1. 安装plspm包 plspm 是一个用于执行偏最小二乘路径建模分析的 r 程序包。 在 CRAN 上可以免费下载: Http://cran.r-project.org/web/packages/plspm/index.html. 此后,通过以下代码在r中安装并加载该程序包即可。 install.packages("plspm") library("plspm") 2. 一些简单概念 2.1. 潜变量和观测变量 不少变量如满意度、成功指数是无法通过观测得到

Wowlittlemoon的博客 1万+

笔记:《C++并发编程实战》

第一章 你好,C++的并发世界 计算机系统中的并发:进行上下文的切换时,操作系统必须为当前运行的任务保存CPU状态和指令指针,并计算出要切换到哪个任务,并为即将切换到的任务重新加载处理器状态。然后CPU可能要将新任务的指令和数据的内存载入到缓存中,这会阻止CPU执行任何指令,从而造成的多的延迟。 多进程并发: 操作系统在进程间提供附加的保护操作和更高级别的通信机制意味着可以更容易编写安全的并发代码。 使用多进程实现并发还有一个额外的优势———可以使用远程连接(可能需要联网)的方式,在不同机器上运行

NiGo的博客 1138

基于FreeRedis实现的.NET Redis客户端缓存缓存键条件优雅过滤

在.NET开发中,使用Redis作为缓存解决方案是很常见的。FreeRedis是一个功能强大的Redis客户端库,它提供了丰富的功能和灵活性,使我们能够轻松地与Redis进行交互。在本文中,我们将探讨如何使用FreeRedis实现缓存键条件的优雅过滤,以提高缓存的效率和准确性。

RzuScala的博客 329

new、delete、以及queue类

本来以为很容易的,结果还是写了我两个小时。 用指针模拟queue类,再加上类,各种错误,总算是解决掉了-- #include&lt;iostream&gt; #include&lt;cstdlib&gt; #include&lt;string&gt; using namespace std; class Item { private: int time; i...

weixin_34247032的博客 152

Xilinx DDR3 MIG IP核设计--汇总导航

快速上手Xilinx DDR3 IP核----汇总篇

孤独的单刀 2万+

Altium Designer(AD24/25)导出DXF或DWG结构文件的方法

DXF(Drawing Exchange Format)和DWG(Drawing)是两种常见的CAD(计算机辅助设计)文件格式,常用于结构和硬件之间的沟通。本文介绍Altium Designer(AD24/25)导出DXF或DWG结构文件的方法。

fydar的博客 2331

使用细粒度锁的c++线程安全队列

使用细粒度锁的c++线程安全队列实现:#include #include #include #include template class threadsafe_queue { private: struct node { std::shared_ptr data; std::unique_ptr next; }; std::unique_ptr head; node* tai

Watson2016的博客 2059

Python 爬虫实战:爬取万方数据文献信息

本文介绍了基于Python爬虫技术合规获取万方数据文献信息的方法。通过分析万方数据的请求机制与反爬策略,采用requests库结合Session维持合法会话,实现了文献标题、摘要、作者等核心元数据的提取。文章详细讲解了Token验证、动态请求构造、JSON数据解析等关键技术,并提供了完整可运行代码。同时强调严格遵守《万方数据知识服务平台用户协议》,控制请求频率,仅限学术研究使用。该方案为万方数据文献信息获取提供了标准化解决方案,支持数据清洗、结构化存储及后续分析应用。

2503_91057718的博客 2137

Multithreading-Cpp-Course:掌握现代C++并发编程的不二选择

Multithreading-Cpp-Course:掌握现代C++并发编程的不二选择 项目介绍 在现代软件开发领域,多线程编程是一个至关重要的技能。它不仅能提升程序的性能和响应速度,还能有效利用多核处理器的能力。Multithreading-Cpp-Course 是一套针对现代C++并发编程的教程源码,源自知名的在线教育平台Udemy上的课程 "Learn Multithreading ...

gitblog_01108的博客 705

团体程序设计天梯赛竞赛题--登顶题【L3-039 攀岩】

登顶级 3 道题,每道题 30 分,满分为 90 分。

Pretty Boy Fox的博客 653

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

探索《C++并发实战》开源项目:掌握现代C++的并发编程艺术

探索《C++并发实战》开源项目:掌握现代C++的并发编程艺术 在软件开发领域,多线程和并发处理已经成为提升程序性能、优化资源利用率的关键技术之一。今天我们要介绍的项目是,一个基于著名书籍《C++ Concurrency in Action》的实践代码库。它提供了丰富的示例,帮助开发者深入理解并熟练应用C++的并发编程。 项目概述 该项目旨在为学习C++并发编程的开发者提供实战案例和实验环境。原书作...

gitblog_00072的博客 1207

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C++ 并发编程实战 第二版

C++ 并发编程实战 第二版 【下载地址】C并发编程实战第二版 《C++ 并发编程实战 第二版》是一本全面解析 C++ 并发编程的权威指南,深入探讨了 std::thread、std::mutex、std::async 等核心工具的使用,以及原子操作和内存模型的复杂机制。本书从基础概念到高级技术,逐步引导读者掌握现代 C...

gitblog_06752的博客 1602

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C++并发编程实战第二版教程

《C++并发编程实战》第二版(C++ Concurrency in Action 2ed)是一本介绍C++11/14/17/20多线程编程的书籍,由Anthony Williams编写。本书详细介绍了线程支持库的基本用法,并从实践角度介绍了并发编程的设计思想。第二版新增了C++17特性,如`std::scoped_lock`、`std::shared_mutex`,并增加了关于C++17标准库并行...

gitblog_00314的博客 856

C++并发编程实战指南

C++并发编程实战指南》是一本深受开发者欢迎的书籍,旨在帮助读者深入理解和掌握C++并发编程的核心技术和实践方法。在《C++并发编程实战指南》中,作者首先介绍了并发编程的基本概念,包括线程、锁、同步、异步等。《C++并发编程实战指南》通过一个详细的线程池实现案例,展示了如何创建和管理线程池,以及如何将任务分配给线程池中的线程执行。并发编程在提高程序性能的同时,也可能引入新的性能问题和调试困难。在掌握了并发编程基础后,《C++并发编程实战指南》进一步介绍了高级并发技术,包括原子操作、内存模型、条件变量等。

2501_92486623的博客 473

《C++ 并发编程实战 第二版》前 4 章 标准库工具及其使用:思维导图

《C++ 并发编程实战 第二版》学习笔记目录下面是 markdown 版本,思维导图只是对书中内容主题的粗略概括,部分知识点的详细研究请关注学习笔记目录当中的相关文章

鱼竿钓鱼干 939

C++并发编程实战资源下载

C++并发编程实战资源下载 【下载地址】C并发编程实战资源下载 本仓库提供了一个名为“C++并发编程实战(全书和源码).zip”的资源文件下载。该文件包含了C++并发编程实战的完整书籍内容以及相关的源代码 项目地址: https:...

gitblog_09732的博客 580

《c++并发编程实战》 笔记

这个新的可调用对象在调用时,会调用原始的可调用对象,并传递给它预先绑定的参数(如果有的话),以及调用新可调用对象时提供的任何额外参数。使用std::shared_future::wait,std::shared_future 与 std::future 类似,但主要区别在于 std::shared_future 可以被多个线程或对象共享,而 std::future 一旦被移动或拷贝后,原始对象将不再持有任何结果,变成空状态。std::call_once 是 C++11 引入的一个函数,它属于 头文件。

qq_42974718的博客 1475

《C++并发编程实战》第二版核心内容解析

《C++并发编程实战》第二版核心内容解析 本书定位与核心价值 《C++并发编程实战》第二版是针对现代C++(C++11/14/17标准)并发编程的权威指南。作为一本系统性的教程,它从基础概念到高级技巧,全面覆盖了C++标准库中的并发编程工具和技术要点。 内容架构深度解析 基础篇(1-5章) 标准库工具入门:详细讲解std::thread、std::mutex等基础组件的使用 异步编程:深入剖析s...

gitblog_00987的博客 595

探索C++并发编程的奥秘:《C++并发编程实战》源码推荐

探索C++并发编程的奥秘:《C++并发编程实战》源码推荐 【下载地址】C并发编程实战源码CConcurrencyinAction 本仓库提供了《C++并发编程实战》(C++ Concurrency in Action)一书的源码资源。这些源码是书中示例代码的完整实现,帮助读者更好地理解和实践C++并发编程的相关概念和技术...

gitblog_09715的博客 385

C++ 并发编程实战第二版:深入理解C++并发编程的艺术

C++ 并发编程实战第二版:深入理解C++并发编程的艺术 【下载地址】C并发编程实战第二版 《C++ 并发编程实战 第二版》是一本全面解析 C++ 并发编程的权威指南,深入探讨了 std::thread、std::mutex、std::async 等核心工具的使用,以及原子操作和内存模型的复杂机制。本书从基础概念到高级技...

gitblog_06740的博客 369

C++ 并发编程实战教程

《C++ 并发编程实战》(C++ Concurrency in Action)是一本深入探讨C++11及其后续标准中并发和多线程编程的书籍。该项目是该书的中文翻译版本,由陈晓伟翻译。书中详细介绍了如何使用C++标准库中的并发工具,如`std::thread`、`std::mutex`、`std::future`和`std::async`等,以及如何编写高效且安全的并发代码。 ## 项目快速启动

gitblog_00144的博客 560
上一篇: C++矩阵库 Eigen 快速入门
早起的虫儿灬
博客等级 码龄10年 54粉丝 114原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值