关于c++:EE2028A-重点分析

EE2028A C ProgrammingLab Exercise 4Submission instructions: Test your code on your computer first before submitting.You must use the code skeleton provided fro Question 1.Feel free to write as many functions as needed for Question 2.Deadline: Wednesday, February 24th / Friday, February 26thConcepts used: Structures, Pointers, Decision-making statements, loops and C Functions.Question 1: [30 Marks]Let us work on the menu of a library. Create a structure containing book information likeaccession number, name of author, book title and flag to know whether a book is issued or not.Create an interactive menu in which the following can be done.Display book informationAdd a new bookDisplay all the books in the library of a particular authorDisplay the number of books of a particular titleDisplay the total number of books in the libraryIssue a book(If we issue a book, then its number gets decreased by 1 and if we add a book, its number getsincreased by 1)To guide your answer, you can follow the code skeleton provided bellow:12Sample Output:Further Instructions:• As shown in the screen-shot above, the initial number of books in the library is 0• Displaying a book’s information should include its four attributes (shown in skeleton code).Use proper printf messages (no standard format is enforced).• Similarly, for adding a book, prompt the user for all four attributes with proper I/O.• For displaying all books of a given author, first prompt the user for the author’s name, thenuse the same display format in question 1 for all books of that author.• Displaying the total number of books in the library should exclude all books for which theissued flag was set to 1• For your report, add at least 5 books to your library and take screenshots demonstratingeach of the Menu’s options.3Question 2: [20 Marks]Consider a five-element integer array, answer the following questions in order. You can eithertake a user input of the array in the range [-9 ; 9] OR hard-code a five-element array in therange [-9 ; 9].1) Write the appropriate code to generate all sub-arrays with at least 2 elements of agiven input array. A subarray is defined as an array that is generated from a given array.Thus, a subarray comprises elements from the given array, and is of smaller length.For example, for a given array [7, 2, -1, 2], bellow is the expected I/O:Note that the sample I/O above is for format illustration purposes only. Your actualanswer needs to handle five-element integer arrays.2) In the example above, if you consider two-element sub-arrays, possible pairs include thefollowing shown in the table below. Observe that (7,2) is listed twice, one for eachoccurrence of 2. Consider each subarray from your list of all generated subarrays with at4least 2 elements, and perform the sum of products for each subarray as shown in theexample above in the table. The sum of products is calculated by considering only theproducts of the pairs (i.e. for sub-array [7, 2, -1], the sum of products is [7x2] + [7x(-1)] +[2x(-1)] = 5. Modify your code from question 1 to match the sample output bellow:3) Complete the function “largestValue” which takes an array and returns an integerdenoting the largest value of the “sum of products” of any of the sub-arrays generatedfollowing guidelines from questions 1&2. Continuing on the same example, your outputshould look like this:5For your report, take screenshots of your final answer to Q3 only as illustrated above. You arerequired to report on three runs of your program with the following inputs:• 8 4 -2 6 -5• -9 4 3 -1 2• 5 -5 0 3 -9

March 26, 2022 · 3 min · jiezi

关于c++:C的移动构造函数和移动赋值运算符

什么是挪动结构在 C++ 11 规范之前(C++ 98/03 规范中),如果想用其它对象初始化一个同类的新对象,只能借助类中的复制(拷贝)构造函数。在C++11中,引入了右值援用,提供了左值转右值的办法,防止了对象潜在的拷贝。而挪动构造函数和挪动赋值运算符也是通过右值的属性来实现的。直观的来讲,挪动结构就是将对象的状态或者所有权从一个对象转移到另一个对象。只是转移,没有内存的搬迁或者内存拷贝所以能够进步利用效率,改善性能。 右值和左值CPU视角的右值和左值通过一个最简答的程序来看一下CPU是如何对待左值和右值的。 void push(int && x){ int y = x;}void push(int & x){ int y = x;}下面程序对应的汇编代码为: push(int&&): push rbp mov rbp, rsp mov QWORD PTR [rbp-24], rdi mov rax, QWORD PTR [rbp-24] mov eax, DWORD PTR [rax] mov DWORD PTR [rbp-4], eax nop pop rbp retpush(int&): push rbp mov rbp, rsp mov QWORD PTR [rbp-24], rdi mov rax, QWORD PTR [rbp-24] mov eax, DWORD PTR [rax] mov DWORD PTR [rbp-4], eax nop pop rbp ret能够看到汇编指令对于右值和左值的解决是完全相同的,因而无论是左值和右值在CPU看来都是完全相同的。 ...

March 25, 2022 · 1 min · jiezi

关于c++:Linux知识读书笔记

Linux IO 子系统传统IO(读/写) CPU copy:用户buffer => 内核buffer ----------------------------------------> 拷贝* 1DMA copy:内核buffer => 硬件 ------------------------------------------------>拷贝 * 1上下文切换:用户态 => 内核态 => 用户态 ------------------------------------->上下文切换 * 2PageCache技术 Linux IO 栈 文件系统层:治理pagecache块层:治理块设施的IO队列,对IO申请进行合并、排序设施层:通过DMA和内存进行交互,负责数据传输IO形式: 传统 Buffer IO:磁盘 => pagecache => 用户空间 -------------------------------------------------------------------------> 拷贝 * 2mmaped- IO:磁盘 => pagecache =>映射到用户空间,把pagecache映射到用户的地址空间外面 -----------> 拷贝 * 1Direct IO:用户态和块IO层做对接,放弃了pagecache,从磁盘间接向用户态拷贝数据;益处:快,DMA拷贝,本人负责cache ----> 拷贝 * 1Buffer IO:偏移 + 长度mmaped IO:数据按页对齐Direct IO:读写是底层存储块设施大小的整数倍Linux内存地址空间 分段机制:逻辑地址 => 线性地址 GDT(段描述符)分页机制:线性地址 => 物理地址碎片 搭档零碎:将闲暇页分为11个链表,每个链表中页块中间断页的大小别离是1、2、4 .. 1024 申请:申请 4 ,看4 有:调配没有:看8,分成两个4,将另一半挂到块大小为4的链表下开释:看搭档是否闲暇,是则合并劣势:合并时地址只有一位不同,十分疾速定位slab零碎: slab 层有三个slab链表,slab-full、slab-partial、slab-empty每个链表有多个page,每个page都分为若干个object劣势: ...

March 21, 2022 · 1 min · jiezi

关于c++:CMPUTC语言设计

CMPUT 379, Assignment 1, Winter 2021University of Alberta / Department of Computing ScienceObjectiveYou are asked to program a C function in a single source file with the following synopsis: struct memregion { void *from; void *to; unsigned char mode; / MEM_RW, or MEM_RO, or MEM_NO /};int get_mem_layout (struct memregion *regions, unsigned int size);When get_mem_layout() is called, it scans the entire memory area of the calling process and returns in regionsthe list of all the different regions comprising the process's address space. By region, we mean a contiguous areaof memory characterized by the same accessibility. Accessibility can have one of three possible values: MEM_RWmeaning read/write accessibility, MEM_RO meaning read-only accessibility, and MEM_NO meaning no accessibility atall (the process does not have memory assigned to it in the particular address range).In essence, your function should try to reference all locations in the address space of the process and find out 1)whether there is readable memory at the respective location or not, and 2) if there is readable memory, whether itis also writable. Note that there exists a unit of memory allocation called a page and for a given page size, itsuffices to determine the accessibility of a single location within each page. Thus, you don't actually have to scanall locations (for example, successive page base addresses will do).The function get_mem_layout() assumes that the output array regions exists and its size, i.e., the number ofentries, is equal to size. The function get_mem_layout() returns the actual number of memory regions locatedin the process's address space, even if it is larger than size. In the latter case, only the first size regions arereturned in the array. The regions must be stored in increasing order of their starting addresses. For eachmemregion, from represents the starting address of the region, and to represents the very last address of theregion. Note that get_mem_layout should NOT produce any output to stdout on its own.2 / 3Additionaly, you will write three driver programs (mem_1.c, mem_2.c, and mem_3.c). Each one of the driverprograms, first invokes the get_mem_layout() function, then prints the entries returned in memregion in ahumanly readable format, then performs a certain action (different for each action), then invokesget_mem_layout() again, and, finally prints the entries of memregion (now the result of the second invocation).You can choose the action of each driver from a set of options. Examples are: a) allocating a massive array withmalloc and initializing it, b) mmap()-ing a large file, c) invoking a recursive function with a considerable depth ofrecursion, d) performing a mathematical function using the standard math library, assuming always you compiledynamically loaded executables, etc.With humanly readable output we mean something mimicking the following format of hexadeciaml addressrange followed byRW, RO or NO (entries shown here are totally fictitious) :0x00000000-0x0742ffff NO0x07430000-0x07442fff RW0x07443000-0x082fffff RO0x08300000-0x0affffff RW0x0b000000-0x2fffffff NO0x30000000-0x3000ffff RO0x30010000-0xafffffff NO0xb0000000-0xffffffff RONotesThere are other ways to determine the memory layout of a process using a variety of tools available under Linux.However, you will have to do it the hard way, i.e., by scanning the memory directly. This is in fact the most reliableway to authoritatively find out what is really there.Note that you will have to intercept memory reference errors and respond to them in a manner meaningful to theobjectives of the exercise. For this, you have to familiarize yourself with UNIX signals and signal handling. Theywill be covered in the labs.Because, by default, the gcc compiler on the lab machines produces 64 bit executable (which corresponds to amassive address space) you are expected to, instead, produce and run 32 bit executables. This is accomplishedwith the –m32 flag.DeliverablesYou should submit your assignment as a single compressed archive file (zip or tar.gz) containing: ...

March 21, 2022 · 5 min · jiezi

关于c++:名字查找

名字查找C++ 有一个准则,就是标识符要先申明,再应用。每一个标识符在应用的时候,都要找到它对应的申明。这个过程,就是名字查找。 在程序的不同构造中,名字查找的规定也不尽相同。上面简述如下。 Unqualified name lookup简略地说,就是独自一个标识符的查找。 名字空间中对标识符的应用名字空间中的应用的标识符须要在应用前,在以后或蕴含它的名字空间中被申明。 名字空间中定义的函数中这包含函数名之后呈现的任何符号,包含参数表中呈现的类型、默认参数等。 其申明须要呈现在应用之前,顺次查找以后块(block),蕴含以后块的块,函数属于的 namespace,该 namespace 的父 namespace。 namespace A { namespace N { void f(); }}void A::N::f() { i = 5; // i 的申明会在以下中央被查找: // 1) A::N::f 中,i 的只用之前 // 2) namespace N // 3) namespace A // 4) 全局名字空间,A::N::f 的定义之前}类定义中的名字类定义中的名字按其是否在一个 complete-class context ,查找跪在不同。 Complete-class context 是指:函数体、函数的默认参数、noexcept-specifier,成员初始化 在 complete-class context 外,申明要在应用之前,查找范畴包含:以后类、基类的成员、蕴含以后类定义的类(如有)或其基类成员、蕴含以后类的函数(如有)、蕴含以后类的namespace。 namespace M { class B { };}namespace N { class Y : public M::B { class X { int a[i]; }; };}// 会在以下地位查找 i 的申明:// 1) class N::Y::X 中,i 应用之前// 2) class N::Y 中, N::Y::X 定义之前// 3) N::Y’s 的基类 M::B// 4) 名字空间 N, N::Y 定义之前// 5) 全局名字空间, N 定义之前在 complete-class context 中,当查找类成员时,并不要求成员申明在标识符应用之前,查找范畴包含:以后块或蕴含的块(如有)、以后类成员或基类的成员、蕴含以后类定义的类(如有)的成员或其基类成员、蕴含以后类的函数(如有)、蕴含以后类的namespace。 ...

March 20, 2022 · 3 min · jiezi

关于c++:COMP-SCI-7306-PageRank

Assignment 3: PageRank, Frequent Item-Setsand ClusteringFormative, Weight (15%), Learning objectives (1, 2, 3),Abstraction (4), Design (4), Communication (4), Data (5), Programming (5)Due date: 11 : 59 pm, 25 March, 20221 Overview (Attention, Different To PreviousAssignments)This assignment must be done individually. This means all the rules regardingindividual submission will apply and the submission must be solely your ownwork. Therefore, we will not use the groups on MyUni. You will need to submiton the assignment page as an individual.2 AssignmentExercise 1 Frequent Item-Sets (30 points)Suppose there are 100 items, numbered 1 to 100, and also 100 baskets, alsonumbered 1 to 100. Item i is in basket b if and only if i divides b with noremainder. Thus, item 1 is in all the baskets, item 2 is in all fifty of the evennumbered baskets, and so on. Basket 12 consists of items 1, 2, 3, 4, 6, 12, sincethese are all the integers that divide 12. Answer the following questions: ...

March 20, 2022 · 3 min · jiezi

关于c++:读书笔记2

负载指数调研负载四因素:CPU + 内存 + 磁盘 + 网络 四因素的欧几里得间隔作为负载指数 CPU资源: CPU利用率:反馈过程对CPU应用状况 Load Average:= Running + Waiting + Uninterruptable,反馈过程对CPU需要状况 二者并非线性关系,CPU利用率低 load average 可能高,此时过程处于期待IO状态 负载平衡伎俩DNS pros:兼容性好 cons:作用无限(没有权重、只有IP地址、因为缓存不实时、不反对服务可用度上报)网关:通过隧道技术可使server看到用户实在ip,并且能够维持会话信息,保障落到同一台server上反向代理:Nginx 正向代理次要是用来解决拜访限度问题。而反向代理则是提供负载平衡、平安防护等作用。哈希规定 轮询weight:依据权重ip hash:同一个用户落到同一个serverurl hashfair:依据响应工夫抉择C++排查内存问题经验谈mprotect 设置 guard page,呈现问题第一工夫core dump,尽可能靠近谬误现场malloc_trim 尽快让 glibc 偿还内存给操作系统(sbrk)what is non virtual thunk一致性哈希算法1. 经典一致性哈希将节点映射到 [0, 2^32 - 1]的环上,同时将数据映射到[0, 2^32 - 1]的环上,查找第一个哈希值大于等于数据哈希值的节点。 更好的做法(防止了一台机器退出导致负载全副落入下一台机器):为每个物理节点调配若干个虚构节点,应用虚构节点作为哈希映射。

March 19, 2022 · 1 min · jiezi

关于c++:Linux常见命令学习

Linux下过程状态详解 top 、uptime 等命令展现出的 load average,并非 CPU load average,而是零碎整体负载,包含了对磁盘资源的申请 然而通常状况下,load average / CPU core number > 1 暗示零碎可能是CPU BOUND 计算公式: load average = TASK_RUNNING + TASK_UNINTERRUPTABLE Linux下过程状态的划分: R:TASK_RUNNINGS:TASK_INTERRUPTABLED:TASK_UNINTERRUPTABLE:这个状态个别呈现在过程与外部设备替换,内核的一些解决流程是无奈被中断的,如果此时容许中断,原有流程被插入一段解决异步信号的流程,过程与外部设备交互过程被中断,那么外部设备可能陷入不可控的状态,因而,此时不响应异步信号(kill -9 无奈杀死)Z:TASK_ZOMBIELinux /proc子系统文档 常见目录项 cmdline:命令行参数cwdexefdmapscgrouptop命令详解 top命令常见参数 -c :输入残缺命令行-H:显示每个线程而非过程的汇总 (通过pthread_setname_np)更敌对-p pid:显示特定过程的信息交互命令: m:切换显示内存的形式t:切换显示CPU负载的形式c:切换显示残缺命令行与否M:按内存排序P:按CPU排序T:按运行工夫排序perf perf record 通过挂载到某个过程上生成 perf.data,perf report 读取perf.data 取得信息address-sanitizer:原理是 shadow poison,可能探测dangling pointer、buffer overflow、memory leak [Use after free] (dangling pointer dereference)[Heap buffer overflow][Stack buffer overflow][Global buffer overflow][Use after return][Use after scope][Initialization order bugs][Memory leaks]iostat命令详解 ...

March 19, 2022 · 1 min · jiezi

关于c++:22种设计模式的C实现

前言1. 代码仓库https://github.com/TOMO-CAT/C...2. 前置常识UML类图与面向对象编程软件设计准则与SOLID准则创立型模式工厂办法模式(Factory Method)形象工厂模式(Abstract Factory)生成器模式(Builder)原型模式(Prototype)单例模式(Singleton)结构型模式适配器模式(Adapter)桥接模式(Bridge)组合模式(Composite)装璜模式(Decorator)外观模式(Facade)享元模式(Flyweight)代理模式(Proxy)行为型模式责任链模式(Chain of Responsibility)命令模式(Command)迭代器模式(Iterator)中介者模式(Mediator)备忘录模式(Memento)观察者模式(Observer)状态模式(State)策略模式(Strategy)模板办法模式(Template Method)访问者模式(Vistor)

March 18, 2022 · 1 min · jiezi

关于c++:软件开发通识之一什么是计算机语言

https://www.toutiao.com/i7076...

March 17, 2022 · 1 min · jiezi

关于c++:CQt-和-WordExcelPDF-交互总结

浏览本文大略须要 6 分钟日常开发软件可能会遇到这类小众需要,导出数据到 Word、Excel 以及 PDF文件,如果你应用 C++ 编程语言,那么能够抉择的计划不是很多,恰好最近刚好有这部分需要,整顿下这段时间踩过的坑,不便前人 读写 Word日常开发的软件应用最多的应该是导出数据到 Word 文档中,目前能够用的计划有这几种 没有美中不足的计划,任何计划都存在长处和毛病,上面来具体看下这几种计划的优缺点以及实用场景 XML 模板替换原理:当时编辑好一份 Word 模板,须要替换内容的中央预留好地位,而后应用非凡字段进行标记,前面应用代码进行全量替换即可实现长处代码量绝对较少、导出速度快跨平台,反对多个零碎,零碎不装置 office 也能导出;反对图片以及固定格局导出;毛病导出格局固定,可扩展性不强,如果需要变动导出格局变了,那么模板也要跟着扭转;一种格局对应一份模板,如果导出格局较多,须要筹备的模板文件较多,这样比拟繁琐;须要 Word 2003 以上版本;举个栗子咱们先编辑一份 Word 模板文档,内容大略如下所示: 将该文档另存为 Word XML 文档 XML-Template.xml读取文档内容进行变量替换 QFile file("XML-Template.xml"); if (!file.open(QIODevice::ReadOnly)) { qDebug() << "open xxml file fail. " << file.errorString(); return 0; } QByteArray baContent = file.readAll(); file.close(); QString strAllContent = QString::fromLocal8Bit(baContent); strAllContent.replace("$VALUE0", "1"); strAllContent.replace("$VALUE1", QString::fromLocal8Bit("法外狂徒张三")); strAllContent.replace("$VALUE2", QString::fromLocal8Bit("考试不合格")); strAllContent.replace("$VALUE3", "2"); strAllContent.replace("$VALUE4", QString::fromLocal8Bit("李四")); strAllContent.replace("$VALUE5", QString::fromLocal8Bit("合格")); QFile newFile("export.doc"); if (!newFile.open(QIODevice::WriteOnly)) { qDebug() << "file open fail." << newFile.errorString();; return 0; } newFile.write(strAllContent.toLocal8Bit()); newFile.close();保留替换后的内容,写入文件 ...

March 17, 2022 · 2 min · jiezi

关于c++:CC气象数据中心实战手把手教你做工业级项目

download:C/C++气象数据中心实战,手把手教你做工业级我的项目2021 年 Node.js 的发展趋势世界各地的开发者对 2021 年 Node.js 的发展趋势做了很多预测。在下文中,咱们将解说往年预期的 Node.js 趋势。Node.js 为什么如此有名呢?近些年来,Node.js 凭借其高度灵活和极其轻量的个性,变得非常流行。Node.js 具备大量的 JavaScript 库用于简化开发流程。Node.js 的开源属性也使得它在 web 和移动利用开发方面变得非常出名。根据最近的统计,可能看出: 目前有超过 50% 的开发者在自己的我的项目中使用 Node.js。在美国,基于 Node.js 创建的网站超过 28000 个 。AliExpress、eBay 等出名公司很大程度上依赖于 Node.js。包含 PayPal、Netflix 和 Groupon 在内的大流量的网站都在使用 Node.js。 Node.js 自 2009 年在市场上推出就变得非常受欢迎。Node.js 在 Github 中具备 75.9k stars、3k watchers,还有 19k forks,在 Stack share 中具备 71.8k 的关注者以及 8.3k 的同意。这些数字足以描述 Node.js 流行程度。出名的科技巨头,比如 Netflix 和 Microsoft 都在使用 Node.js。Node.js 胜利在 StackOverflow 2021 年开发者考察中位居榜首,其中超过 50% 的考察参与者声称正在我的项目中使用 Node.js。

March 16, 2022 · 1 min · jiezi

关于c++:typetraits源码阅读笔记

// enable_iftemplate <bool, typename _Tp = void>struct enable_if {};template <typename _Tp>struct enable_if<true, _Tp>{ typedef _Tp type; }// integral_constanttemplate<typename _Tp, _Tp __v>struct integral_constant{ static constexpr _Tp value = __v; typedef _Tp value_type; typedef integral_constant<_Tp, __v> type; constexpr value_type operator()() const noexcept { return value; }};/// The type used as a compile-time boolean with true value.typedef integral_constant<bool, true> true_type;/// The type used as a compile-time boolean with false value.typedef integral_constant<bool, false> false_type;<type_traits> 值得好好读 ...

March 14, 2022 · 1 min · jiezi

关于c++:初始化-Initialization

初始化 (Initialization)初始化的模式 Direct-initializationCopy-initialization初始化的含意Value initializeDefault initializeZero initializeList initialize narrowing conversion字符数组初始化聚合(aggregate)初始化 Aggregate援用初始化基于c++20 draft n4868 初始化的模式通常讲到初始化,会想起变量的时候给的初始化值(initializer)。然而除此之后,还有一些中央会产生对象的初始化。所有的这些初始化操作听从同一套规定。 初始化依照其模式,能够分为两大类,direct-initialization与copy-initialization Direct-initialization变量定义中初始化值无= int i{1}; std::vector<std::string> vec(3);new-initializer int *p = new int(3);,应用3初始化一个新建的int对象static_cast static_cast 会应用其参数初始化一个后果类型的对象,如:static_cast<int>(2.0);,其中应用2.0初始化一个int对象。函数调用像是的类型转换 int(2.0),其中应用2.0初始化一个int类型的对象condition 中的 brace-init-list if (Derived *pDerived{dynamic_cast<Derived*>(pBase)}),应用 dyanmic_cast<Drived*>(pBase) 初始化 pDerivedCopy-initialization变量定义中应用 = 模式初始化 int i = 1; ,应用 1 初始化 icondition 中应用 = 模式初始化 if (Derived *pDerived = dynamic_cast<Derived*>(pBase)),应用 dyanmic_cast<Drived*>(pBase) 初始化 pDerived参数传递,函数返回值 示例: int foo(int i) { return i+1;}void bar() { foo(1);}应用 1 初始化 foo 的参数 i,应用 i+1 初始化函数的返回值(右值) ...

March 13, 2022 · 4 min · jiezi

关于c++:sharedptr源码阅读

能够通过模板参数指定Lock_Policy class sp_counted_Base{} use_count => 当减为0析构资源 disposeweak_count => 当减为0 delete this; destroy开释管制区域 二者皆为原子变量,原子操作扭转值,同时应用内存屏障确保可见性 dispose肯定要能被调用destroy的线程察看到 class sp_counted_Ptr{} 继承了 sp_counted_Baseclass sp_counted_deleter{} 继承了sp_counted_Base,存储了Deleter_,应用std::addressof 1获取地址 十分乏味,当面对模板时,传入的类型的& operator可能被重载,并非取地址的含意,因而应用这个补救。 why use std::addressof versus &: https://stackoverflow.com/que... ↩

March 12, 2022 · 1 min · jiezi

关于c++:SOF103

DESCRIPTION OF COURSEWORKCourse Code SOF103Course Name C and C++ ProgrammingLecturer Dr. Kamran SiddiqueAcademic Session 202009Assessment Title Project (Replacement of Class Test)A. Introduction/ Situation/ Background InformationThe key characteristics of object oriented programming (OOP) are encapsulation, inheritance, andpolymorphism. In order to comprehend and utilize the advantages of the OOP, a project has beendesigned to simulate the working of a banking account system. The students are expected toimplement it with an effective utilization of the characteristics of OOP focusing constructors, datahiding and abstraction techniques, code reusability, virtual functions, input validations, and so on.This activity also highlights the significance or report writing and effective presentation.B. Course Learning Outcomes (CLO) coveredAt the end of this assessment, students are able to:CLO 1 Comprehend basic programming constructs of C and C++.CLO 2 Demonstrate an understanding of the concepts and principles of C and C++programming by solving real-world problems in particular.CLO 4 Evaluate the given C/C++ code segments using algorithm tracing technique.C. University Policy on Academic Misconduct ...

March 12, 2022 · 8 min · jiezi

关于c++:读书笔记之智能指针广度搜索

make_shared和shared_ptr<T>()的比拟make_shared只进行一次堆内存调配,shared_ptr<T>()进行两次堆内存调配 make_shared :将对象Object 和 管制块Control Block调配到一起shared_ptr<T>() :先new Object,再调配Contrl Block造成的结果: Exception safety:函数 f 接管两个 shared_ptr A、B作为参数,那么经验四个步骤 new Anew Bshared_ptr<T>(A)shared_ptr<T>(B)如果步骤2抛出异样(例如OOM),那么A对象没有被回收,因为此时A对象没有被智能指针治理起来,造成了资源泄露。 这个问题在C++17中失去了解决,C++17对函数参数求值程序做了规定,规定了函数参数求值须要 fully evaluate后 能力对下一个参数进行求值 Disadvantage of make_shared:weak_ptr的存在使得对象可能永远得不到开释。 因为weak_ptr的实现原理,是依据Control Block中的援用计数来判断对象是否被开释,因而Control Block的生命周期至多要和weak_ptr一样长。而make_shared在一次调配中调配了对象和Control Block的空间,因而只有对象和Control Block都不再应用的时候,能力进行开释。这就导致了即便援用计数为0,对象也没有被开释,直到最初一个weak_ptr析构,资源能力被一起开释。而shared_ptr因为是两次调配,能够别离开释。noexcept 和 stack unwind 和 FPOnoexcept 申明函数不抛出异样,不便编译器优化(应用move),对于big four(constructor 、 assignment 效果显著)。也能够在编译期对不同类型判断是否会抛出异样。 保障不抛出异样,编译器就不用进行Exception Handling FPO1: 问题起源:如何索引栈上变量? 计划一:通过esp进行偏移索引。毛病是esp会产生变动,要求编译器生成的代码更简单。 计划二:通过ebp进行偏移索引,ebp在一个栈帧中是固定的,更简略。 必须应用ebp的场景 SEH 当解决异样时,不能通过esp正确索引栈上变量,因为esp可能曾经产生变动具备destructor的对象必须应用SEH来取得unwind support应用alloca动态分配栈上数组,则必须 应用ebp,因为编译器无奈取得变量对esp的偏移=> 大部分场景 FPO disabled FPO disabled的益处:能够在缺失符号的状况下,依据ebp,将栈当作链表串起来 FPO的劣势: 1. x86寄存器太少,多一个寄存器能够少在栈上调配空间,访存更快 2. 没有保留、复原ebp的开销,代码提交更小custom deleter in smart_ptrstd::function => 32 bits on x64 payload of unnecessary flexibilityfunction ptr => 8 bits on x64stateless lambda => 0 EBOstateful lambda => sizeof (lambda)关注引起的 smart_ptr size 变动2 ...

March 11, 2022 · 1 min · jiezi

关于c++:RBE104TC-分析

RBE104TC C/C++ Programming LanguageAssignment 2 Assignment Overview:This assignment aims at testing some basic concepts of the C++ programming andinitiates the routine of code development using the software development process(SDP) presented in the relevant lectures. It focuses on the following five steps ofthe SDP. Problem statement: formulate the problem;Analysis: determine the inputs, outputs, variables, etc.;Design: define the list of steps (the algorithm) needed to solve theproblem;Implementation: the C code has to be submitted as a separate file, justindicate here the name of the file;Testing: explain how you have tested and verified your C program.You will need to apply this methodology to each one of the following simpleexercises.Things to note:Include clear comments in your code to make it easy to understand.Explain your testing procedure and what you have observed during thetesting. The testing should be demonstrated by screenshot pictures topresent the actual implementation output.How you solved any problems.Contribution to the Overall Marks 60%Issue DateSubmission Deadline Dec. 23rd, 2020/ 5Exercise 1:Design a new class to represent a fraction (anation of two integer values).The data members of the class Fraction are twointegers, top and down, denoting the numeratorand denominator, respectively.class Fraction{private:int top; // Numeratorint bottom; // Denominatorpublic:. . . . . .};Part 1: Fundamental requirements for the class Fraction.Fractional numbers can be declared with both a numerator and denominator,or simple numerator:Fraction a; // represents 0/1Fraction b(3,4); // represents 3/4Fraction c(5); // represents 5/1Fractions should be able to act just like other numbers.Add, subtract, multiple and divide;Compare based on values;Input and output.Part 2: Advanced requirementsFractional number is normalized to ensure that only the numerator can benegative and the value is in the least common denominator form:• 2/-3 would be converted into -2/3 automatically;• 15/21 would be converted into 5/7 automatically.Write methods to convert between decimals and fractions.Exercise 2:Derive a sub-class iFraction from the base class Fraction, which was designed byyou in Exercise 2 of Assessment 2. The iFraction class represents the mixedfractions like ;Part 1: Design the sub-class iFraction:• It should have a constructor for initialisation;• It should contain a method to display the mixed fraction on screen;Part 2: Design an external function convertF (not function member of class Fractionand iFraction) to convert the improper fractions to mixed fractions.Hint: convertF can be the friend function of those two classes.Exercise 3:Design a composite class that represents complex numbers whose real andimaginary parts are Fractions.• Write appropriate constructors for this class;• Complex numbers should be able to add, subtract and multiple./ 5Exercise 4:This is a computer game with different types of players. Take the code provided forthe container class (container.h), player class (player.h), and the swordsman class(swordsman.h), and the main function (main.cpp).Part 1:Read the source codes, understand the meaning and fill the blank (shownas) to make it work;Generate the CRC cards of the classes: clarify the responsibilities of eachclass, illustrate the collaboration with others, and label all the members’ aspublic, protected, and private. Then draw the hierarchy chart of them;Part 2:Design another two classes, archer and mage. Generate their CRC cardand put them in the hierarchy chart drew above. Write the code for these twoclasses and make them work (cooperate with the main function);Modify the main function, to have enemies with all three professions (couldbe randomly chosen).Part 3 (Optional): Can you involve another attribute – luck, in this game?Notes: The factors are imperfect, make the fight too hard or too easy. Changewhatever you want, but leave hints for reviewers to know what you have done./ 5What should be submitted?You should submit the followings:1). A short report (up to a few pages of text plus C source codes) detailing for eachquestion:a). SDP steps 1 to 3 in the report (Report + Specification + Analysis +Algorithm Design) (40%);b). SDP step 4 (Implementation + Robustness): your C source code includingthe comments. (40%);c). SDP step 5 (testing): you will explain how you have tested the correctnessof your C program and will include some sample runs of your C Programs.(20%);Please refer to the file Marking Guidelines for RBE104TC.pdf on the Learning Mallsystem for a detailed marking scheme.2). The report in Microsoft Word or pdf format and C source code of yourimplementation zipped into a single file, i.e. the zip file will contain 2 files. (It is goodpractice to include comments in your code see the example provided.)The naming of Report (.doc, .docx or .pdf only), Source Code (.c) and Compressedfile (.zip, or .rar only)StudentID_LastName_FirstName_AssignmentNumber.docStudentID_ AssignmentNumber.cStudentID_LastName_FirstName_AssignmentNumber.zipFor example:Report and c source file named:1234567_Albert_Einstein_1.doc1234567_1.cContained within the zip file:1234567_Albert_Einstein_1.zipHow the work should be submitted?Should be submitted electronically through the Learning Mall system so that themarker can run your programs during marking. Feedback and your grade will alsobe given through the Learning Mall system.

March 11, 2022 · 4 min · jiezi

关于c++:读书笔记

调试Crash-g 保留了源码级别的调试信息(变量名称、函数名称、代码行的映射),能够通过strip或者objcopy删去调试信息。依据core dump产生时的调用栈和代码行号信息去看源代码。利用gdb调试core文件,查看堆栈以及变量。内存被毁坏,个别状况下core的时候曾经不是内存毁坏的第一现场了(早就被毁坏了)SEGV_MAPPER => 没有被映射(空指针、低地址指针)SEGV_ACCERR => 没有权限(试图批改只读区域)64位零碎中,0x0000000007fffffffffffff 以下为user,0xfffffffffffff8000000以上为kernel。 低地址、空指针问题虚函数调用问题:越界、溢出导致this被写坏,虚指针指向谬误,导致运行时谬误。野指针、空悬指针无栈协程无栈协程不会进行寄存器级别的上下文保留和复原,只是将函数执行到的地位记录在协程对象的成员变量中,协程函数通过switch case 和 跳转宏,在复原执行时跳转到指定地位执行。并非没有stack,而是在以后的stack下面创立协程栈帧,不会为协程指定独立的stack空间。 有栈协程能够在嵌套的栈帧中暂停(随时随地挂起),无栈协程只能在顶层栈帧暂停,在协程中调用的函数不能被暂停。 无栈协程应用宿主栈,没有独自协程栈。 对称协程 vs 非对称协程对称协程提供 pass control 语义(交出控制权),非对称协程提供 yield、resume语义,由管制协程进行调度。

March 10, 2022 · 1 min · jiezi

关于c++:zbh的协程学习总结

IO倒退历程1从同步IO谈起 长期以来,应用C/C++编写服务器程序的时候,应用的往往是多过程模式:一个父过程负责 accept 传入连贯,而后 fork 一个子过程解决;或者是一个父过程创立了一个 socket 之后,fork 出多个子过程同时执行 accept 和解决,(例如Apache Http Server 2.4版本前,采纳per request per thread模型2)。 这时候个别应用同步IO来解决,也就是应用阻塞的read、write,当过程被IO阻塞的时候挂起过程。益处是这种同步开发方式和人类思维相近,编写简略。害处之一是效率低:随着C10K问题3的提出,在高并发场景下,cpu忙于过程或线程的切换,大量cpu工夫被节约。 异步IO降临 所谓异步IO,就是发动IO申请的线程不等IO操作实现,就继续执行随后的代码,IO后果用其余形式告诉发动IO申请的程序。 最简略的情景就是通过设置O_NONBLOCK标记应用非阻塞的read、write,定时轮询资源是否可用。如果资源不可用,会返回相应的谬误如EAGAIN。 然而在并发量很大时,cpu同样失陷于轮询中,效率很低(次要是每次都要进行零碎调用,开销大)。有没有什么办法让咱们被动接管资源就绪的告诉,而不是一一被动轮询呢?在Linux下,咱们能够应用select/poll/epoll来同时监听多个文件描述符,看似将非阻塞IO阻塞在了select/poll/epoll中,然而这种形式监听了多个描述符,而且防止了大部分无用的零碎调用开销。 益处是高效:没有切换上下文的开销、没有过程间同步、通信问题,然而害处是开发不便。异步IO须要配合基于事件驱动的异步开发模式。在EventLoop中,什么事件到来,就调用相应的回调函数进行解决,和传统同步思维有很大不同。(std::function满天飞~,容易毁坏逻辑的连续性)。 协程退场 有种说法是协程是一种轻量级的线程,这是针对它不须要操作系统调度染指、开销小而言,然而我感觉不够精确。实质上,协程就是一个能够暂停的函数,遇到阻塞的时候,就让出cpu,当条件满足了就持续复原运行。 从另一个角度来说,协程和过程、线程的区别就是两点 – 是否隔离变量,是否主动切换运行上下文。满足这两点区别的,就是协程。 过程:变量隔离,主动切换运行上下文线程:不变量隔离,主动切换运行上下文切换协程:不变量隔离,不主动切换运行上下文切换在不隔离变量的状况下,主动切换运行上下文,几乎就是 bug 之源,这两件事基本就不该同时反对。当前线程这个货色,应该被扫进历史的垃圾堆,线程带来的便当,比起它挖出的坑相比,有余一提。4 之所以在协程的总结小文中上来就谈到这么多IO相干内容,是因为C++中的协程和IO有很大关系。协程实用于IO密集型利用,而非CPU密集型利用。协程的 暂停期待条件满足后复原执行 的特点人造适宜IO。当文件描述符不可读/不可写时,让出cpu;可读/可写后被复原执行,持续解决相应逻辑。让出cpu的动作与同步IO中过程/线程被阻塞而挂起相似,然而防止了过程/线程调度开销,而保留了同步IO的同步开发方式。这正是协程的弱小之处: 并发 + 同步5。 协程分类6协程能够依照以下 3 个角度进行分类 对称/不对称:前者提供让出执行权的原语,后者提供唤起协程和把执行权转交给调用者的原语第一类/受限:协程是不是第一类对象有栈/无栈:协程能在调用栈的任意处挂起,还是只能在协程的函数体内挂起这里看第三个分类的区别: 此处「有栈」和「无栈」的含意不是指协程在运行时是否须要栈,对于大多数语言来说,一个函数调用另一个函数,总是存在调用栈的; 而是指协程是否能够在其任意嵌套函数中被挂起,此处的嵌套函数能够了解为子函数、匿名函数等。显然有栈协程是能够的,而无栈协程则不能够。 它们的次要区别是:有栈协程能在调用栈的任意处挂起,无栈协程只能在协程的函数体内挂起。 有栈协程很多中央又把协程称为 subroutine,subroutine 是什么,就是函数。上古期间的计算机科学家们早就给出了概念,coroutine 就是能够中断并复原执行的 subroutine,从这个角度来看协程领有调用栈并不是一个奇怪的事件。 咱们再来思考 coroutine 与 subroutinue 相比有什么区别,你会发现区别仅有一个,就是 coroutinue 能够中断并复原,对应的操作就是 yield/resume,这样看来 subroutinue 不过是 coroutinue 的一个子集罢了。 也就是说把协程当做一个非凡的函数调用,有栈协程就是咱们现实中协程该有的模样。 既然把其当做一个非凡的函数调用,对咱们来说最严厉的挑战就是如何像切换函数一样去切换协程,难点在于除了像函数一样切换进来,还要在某种条件满足的时候切换回来,咱们的做法能够是 在协程外部存储本身的上下文,并在须要切换的时候把上下文切换就能够了。 ...

March 9, 2022 · 9 min · jiezi

关于c++:xmake-v264-发布大量包管理特性改进

Xmake 是一个基于 Lua 的轻量级跨平台构建工具。 它十分的轻量,没有任何依赖,因为它内置了 Lua 运行时。 它应用 xmake.lua 保护我的项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对老手十分敌对,短时间内就能疾速入门,可能让用户把更多的精力集中在理论的我的项目开发上。 咱们可能应用它像 Make/Ninja 那样能够间接编译我的项目,也能够像 CMake/Meson 那样生成工程文件,另外它还有内置的包管理系统来帮忙用户解决 C/C++ 依赖库的集成应用问题。 目前,Xmake 次要用于 C/C++ 我的项目的构建,然而同时也反对其余 native 语言的构建,能够实现跟 C/C++ 进行混合编译,同时编译速度也是十分的快,能够跟 Ninja 持平。 Xmake = Build backend + Project Generator + Package Manager我的项目源码官网文档入门课程新个性介绍更灵便的包扩大当初,咱们能够通过 set_base 接口去继承一个已有的包的全副配置,而后在此基础上重写局部配置。 这通常在用户本人的我的项目中,批改 xmake-repo 官网仓库的内置包比拟有用,比方:修复改 urls,批改版本列表,装置逻辑等等。 例如,批改内置 zlib 包的 url,切到本人的 zlib 源码地址。 package("myzlib") set_base("zlib") set_urls("https://github.com/madler/zlib.git")package_end()add_requires("myzlib", {system = false, alias = "zlib"})target("test") set_kind("binary") add_files("src/*.c") add_packages("zlib")咱们也能够用来单纯增加一个别名包。 package("onetbb") set_base("tbb")咱们能够通过 add_requires("onetbb") 集成装置 tbb 包,只是包名不同而已。 包治理反对工具链切换之前,咱们限度了只能在 cross 平台下切换包装置的工具链,新版本中,咱们能够反对更多平台下,对工具链的切换。 ...

March 8, 2022 · 2 min · jiezi

关于c++:C的引用类型的掌握

援用类型是C++新减少的一个类型,也是十分体现C++特点的一个类型,始终晓得其是别名,但具体含意必须精确把握,能力精确的利用,其留神点如下: 1、定义:援用是已定义的变量的别名(另一个名称) 2、用处:援用变量的主要用途是用作函数的形参 3、应用注意事项:必须在申明援用时进行初始化(援用更靠近const指针,必须在创立时进行初始化,一旦与某个变量关联起来,就将始终效忠于它) 这三点记住,就能够说把握了援用的用法,哪一点不了解到位,应用过程中都报错。 比方第一点,定义,援用是已定义的变量的别名,其含意就是首先存在一个变量,这是前提条件,否则的话,编译就会报错,用一个例子展现一下: 1 #include <iostream> 2 #include <stdio.h> 3 4 int getMax(int &a, int &b) 5 { 6 int max; 7 if(a > b) 8 max = a; 9 else 10 max = b; 11 return max; 12 } 13 14 int main() 15 { 16 using namespace std; 17 int a1 = 2; 18 int b1 = 3; 19 int max = getMax(2, 3); 20 printf("max = %d\r\n", max); 21 int max = getMax(a1, b1); 22 printf("max = %d\r\n", max); 23 return 0; 24 }是不是,看着下面的代码挺失常的,我一开始也是感觉这样的,间接隐形转化不就能够了,理论不是这样的,如果你这样想,编译就开始打你耳光了。 ...

March 7, 2022 · 2 min · jiezi

关于c++:C与QT的sprintf的用法

反正常常用sprintf这个函数,因为太好用了吧。 通过这个,能够拼字符串,包含各种类型的变量,都能够组装到外面,拼字符串是程序最常常的一个操作了,能够说,很多程序就是组装字符串的过程,记得一个同学以前说过:程序的实质不就是解决数据吗?是啊,就是这点事。 用法是统一的,如下: C 库函数 int sprintf(char str, const char format, ...) 发送格式化输入到 str 所指向的字符串这就是他们独特的中央,不同的就是QT通过面向对象封装了一下,如此而已。上面总结了在C++与QT当中这种函数的用法,很简略,两者比照着记,印象更深一些吧: void MainWindow::on_pushButton_3_clicked(){ //1、c++的字符串格式化 char a[12] = "this is c "; char b[64] = {0}; sprintf(b, "function %s ", a); qDebug()<<b; //2、QT的字符串格式化 QString info = "this is a test"; //1.1/QT的第一种用法,实例调用法: QString test; test.sprintf("function:%s", info.toStdString().c_str()); qDebug()<<info; qDebug()<<test; //1.2/QT的第二种用法,动态调用法: QString info2 = QString::asprintf("function:%s", info.toStdString().c_str()); qDebug()<< info2;}输入状况如下: function this is c "this is a test""function:this is a test""function:this is a test"

March 7, 2022 · 1 min · jiezi

关于c++:C-workflow异步调度框架-架构设计篇

最近在致力同步保护SegmentFault的文章积攒~不便后续继续更新~ 原文是2019年7月底开源后陆续po的,这里对近况进行了调整和补充。 心愿本人和我的项目都能够继续提高 (╹ヮ╹)ノ 欢送多多交换!!尽管我更新本博客比较慢,然而github上的workflow我的项目自身在继续更新中~这一年多以来改了好多好多。这里仅列出一些根本的特点: 包含通信、计算、文件IO、定时器、计数器等异步资源创新性引入的工作流概念,各种异步工作都能够被对等地组装起来实现简单的业务逻辑外部自带多种通用协定,包含http,redis,mysql和kafka等跨平台、反对多种操作系统自带命名服务,包含过程内服务治理与负载平衡,轻松构建微服务零碎实用于实现任何计算与通信关系非常复杂的高性能高并发的后端服务附上github地址: https://github.com/sogou/workflow 明天我还是要抱着跟大家学习的心态,急不可待要从整体的角度来写一下workflow的架构。并且郑重声明一下,本篇只是自己作为开发者之一、想尽快和大家学习交换而写的集体梳理,咱们并没有官网号或公司内其余技术号去发文章,所以这里就当做是其中一个开发者的一丢丢分享了~ 架构设计必然是从底向上开始,所以咱们间接从kernel目录的设计思路开始聊。 1. 封装调度器上次说到,咱们作为异步调度框架,目前反对的异步调度资源分为6种: 这里能够举大家平时接触最多的网络通信框架和计算调度框架作为重点解说一下。 咱们须要封装调度器去操作这些系统资源,简略来说就是操作一批网络连接或者说线程。留神这里说的“操作”,也就是说调度器远不止连接池和线程池那么简略,咱们要做的事件是: 蕴含与治理资源池实现如何对一批连贯尽可能高性能地响应其读写、如何尽可能快且尽可能通用地给出一个足够灵便的机制去让各线程执行各种计算提供申请接口给下层应用咱们以线程执行器Executor为例来看看具体怎么做。以上第二点尽可能快又足够灵便的机制,就是咱们设计的ExecQueue,在以下代码得以体现: class Executor{public: // 一次要执行的接口,对于线程执行器来说,就是把一个执行工作扔进某个队列中 int request(ExecSession *session, ExecQueue *queue);private: // 执行器和系统资源,是一个蕴含关系 thrdpool_t *thrdpool;};2. 封装调度的根本单位构思完了调度器,咱们须要构思一下被调度的根本单位。 对应每种能够调度对象的零碎接口,咱们必须封装本人的构造,作为每次与系统资源交互的根本单位,通过调度器提供的申请接口,扔到调度器里被调度。 具体来说,这显然是一次网络交互、或者一次线程须要执行的计算工作。而后每个根本单位上,能够有上下文、供子类做具体实现的接口/函数指针等等。 咱们以网络交互为例: class CommSession{ // 往连贯上要发的数据 virtual CommMessageOut *message_out() = 0; // 连贯上收到数据流,如何切下一个数据包 virtual CommMessageIn *message_in() = 0; // 本次网络事件被响应的机会 virtual void handle(int state, int error) = 0; … // 个别咱们的上下文是存在派生类上};阶段性总结一下,写到这里,咱们就能够欢快地做网络收发或者线程调度了~这些模块都曾经是能够独自拆出来用的。 作为框架,咱们基于上述的多种调度器和调度单位,能够给用户封装各种具体网络协议和计算算法。然而这还不是咱们的串并行任务零碎的外围价值。 3. 工作流咱们想要实现工作流(无论是DAG还是串并连),意味着咱们须要一套机制去按程序触发具体的子工作执行、并接管其执行完之后要做的事件。实现的形式有很多,咱们做了一套子工作零碎来满足形象的任务调度,而这个工作自身是网络通信还是计算,都不重要。 因为咱们的子工作是要给异步框架用的,所以每个工作你不能只有一个接口:execute()之类,咱们必须有开始执行的dispatch()和执行结束的done()两个须要实现,而工作流零碎自身只是做按程序调起你的开始和完结这两个接口的事件。 class SubTask{ // 子工作被调起的机会 virtual void dispatch() = 0; // 子工作执行实现的机会 virtual SubTask *done() = 0; // 外部实现,决定了工作流走向 void subtask_done(); … };对于工作流,之后会具体介绍其概念,有做相似事件的小伙伴欢送多多交换互相学习,我也会多翻阅一些材料再写,这是十分十分有意思的一个主题。 ...

March 7, 2022 · 2 min · jiezi

关于c++:2022武汉中科创达技术面试C开发工程师

自我介绍-英文Hello, interviewer, my name is **. I am from the School of Computer Science, Wuhan University of Technology, majoring in Internet of Things Engineering. My undergraduate gpa is 3.58, ranking in the top 5% of my major. Courses studied during the undergraduate course include object-oriented programming, algorithms and data structures. My hobbies are playing basketball and running. This concludes my self-introduction, thank you! 业余问题1.过程与线程问题2.static变量作用 总结这家很水,惟一惊喜之处在于英文的自我介绍。没有金山有程度,顺利通过计面。

March 6, 2022 · 1 min · jiezi

关于c++:聊聊第一个开源项目内网穿透-CProxy

文章首发:聊聊第一个开源我的项目 - CProxy 作者:会玩code 初衷最近在学C++,想写个我的项目练练手。对网络比拟感兴趣,之前应用过ngrok(GO版本的内网穿透我的项目),看了局部源码,想把本人的一些优化想法用C++实现一下,便有了这个我的项目。 我的项目介绍CProxy是一个反向代理,用户可在本人内网环境中启动一个业务服务,并在同一网络下启动CProxyClient,用于向CProxyServer注册服务。CProxyClient和CProxyServer之间会创立一个隧道,外网能够通过拜访CProxyServer,数据转发到CProxyClient,从而被业务服务接管到。实现内网服务被外网拜访。 我的项目地址https://github.com/lzs123/CProxy.git应用办法bash build.sh// 启动服务端{ProjectDir}/build/server/Server --proxy_port=8090 --work_thread_nums=4(另一个终端) // 启动客户端{ProjectDir}/build/client/Client --local_server=127.0.0.1:7777 --cproxy_server=127.0.0.1:8080我的项目亮点应用epoll作为IO多路复用的实现数据转发时,应用splice零拷贝,缩小IO性能瓶颈数据连贯和管制连贯接耦,防止相互影响采纳Reactor多线程模型,充分利用多核CPU性能流程架构角色LocalServer: 内网业务服务CProxyClient: CProxy客户端,个别与LocalServer部署在一起,对接CProxyServer和InnerServerCProxyServer: CProxy服务端PublicClient: 业务客户端数据流PublicClient先将申请打到CProxyServer,CProxyServer辨认申请是属于哪个CProxyClient,而后将数据转发到CProxyClient,CProxyClient再辨认申请是属于哪个LocalServer的,将申请再转发到LocalServer,实现数据的转发。 工作流程先介绍CProxyServer端的两个概念: Control:在CProxyServer中会保护一个ControlMap,一个Control对应一个CProxyClient,存储CProxyClient的一些元信息和管制信息Tunnel:每个Control中会保护一个TunnelMap,一个Tunnel对应一个LocalServer服务在CProxyClient端,也会保护一个TunnelMap,每个Tunnel对应一个LocalServer服务,只不过Client端的Tunnel与Server端的Tunnel存储的内容略有差别 启动流程CProxyServer实现几种工作线程的初始化。监听一个CtlPort,期待CProxyClient连贯。CProxyClient实现对应线程的初始化。而后连贯Server的CtlPort,此连贯称为ctl_conn, 用于client和server之前管制信息的传递。申请注册Control,获取ctl_id。最初再依据Tunnel配置文件实现多个Tunnel的注册。须要留神的是,每注册一个Tunnel,Server端就会多监听一个PublicPort,作为内部拜访LocalServer的入口。数据转发流程Web上的PublicClient申请CProxyServer上的PublicPort建设连贯;CProxyServer接管连贯申请,将public_accept_fd封装成PublicConn。CProxyServer通过ctl_conn向client发送NotifyClientNeedProxyMsg告诉Client须要创立一个proxy。Client收到后,会别离连贯LocalServer和CProxyServer: 3.1. 连贯LocalServer,将local_conn_fd封装成LocalConn。 3.2. 连贯ProxyServer的ProxyPort,将proxy_conn_fd封装成ProxyConn,并将LocalConn和ProxyConn绑定。CProxyServer的ProxyPort收到申请后,将proxy_accept_fd封装成ProxyConn,将ProxyConn与PublicConn绑定。尔后的数据在PublicConn、ProxyConn和LocalConn上实现转发传输。 连贯治理复用proxy连贯为了防止频繁创立销毁proxy连贯,在实现数据转发后,会将proxyConn放到闲暇队列中,期待下次应用。proxy_conn有两种模式 - 数据传输模式和闲暇模式。在数据传输模式中,proxy_conn不会去读取解析缓冲区中的数据,只会把数据通过pipe管道转发到local_conn; 闲暇模式时,会读取并解析缓冲区中的数据,此时的数据是一些管制信息,用于调整proxy_conn自身。 当有新publicClient连贯时,会先从闲暇列表中获取可用的proxy_conn,此时proxy_conn处于闲暇模式,CProxyServer端会通过proxy_conn向CProxyClient端发送StartProxyConnReqMsg,CLient端收到后,会为这个proxy_conn绑定一个local_conn, 并将工作模式置为数据传输模式。之后数据在这对proxy_conn上进行转发。 数据连贯断开解决close和shutdown的区别 close int close(int sockfd)在不思考so_linger的状况下,close会敞开两个方向的数据流。 读方向上,内核会将套接字设置为不可读,任何读操作都会返回异样;输入方向上,内核会尝试将发送缓冲区的数据发送给对端,之后发送fin包完结连贯,这个过程中,往套接字写入数据都会返回异样。若对端还发送数据过去,会返回一个rst报文。留神:套接字会保护一个计数,当有一个过程持有,计数加一,close调用时会查看计数,只有当计数为0时,才会敞开连贯,否则,只是将套接字的计数减一。 shutdown int shutdown(int sockfd, int howto)shutdown显得更加优雅,能管制只敞开连贯的一个方向 howto = 0 敞开连贯的读方向,对该套接字进行读操作间接返回EOF;将接收缓冲区中的数据抛弃,之后再有数据达到,会对数据进行ACK,而后轻轻抛弃。howto = 1 敞开连贯的写方向,会将发送缓冲区上的数据发送进来,而后发送fin包;应用程序对该套接字的写入操作会返回异样(shutdown不会查看套接字的计数状况,会间接敞开连贯)howto = 2 0+1各操作一遍,敞开连贯的两个方向。我的项目应用shutdown去解决数据连贯的断开,当CProxyServer收到publicClient的fin包(CProxyClient收到LocalServer的fin包)后,通过ctlConn告诉对端,对端收到后,调用shutdown(local_conn_fd/public_conn_fd, 2)敞开写方向。等收到另一个方向的fin包后,将proxyConn置为闲暇模式,并放回闲暇队列中。 在解决链接断开和复用代理链接这块遇到的坑比拟多 管制对端去shutdown连贯是通过ctl_conn去告诉的,可能这一方向上对端的数据还没有全副转发实现就收到断开告诉了,须要确保数据全副转发完能力调用shutdown去敞开连贯。从闲暇列表中拿到一个proxy_conn后,须要发送StartProxyConnReq,告知对端开始工作,如果此时对端的这一proxy_conn还处于数据传输模式,就会报错了。数据传输数据在Server和Client都需进行转发,将数据从一个连贯的接收缓冲区转发到另一个连贯的发送缓冲区。如果应用write/read零碎调用,整个流程如下图 数据先从内核空间复制到用户空间,之后再调用write零碎调用将数据复制到内核空间。每次零碎调用,都须要切换CPU上下文,而且,两次拷贝都须要CPU去执行(CPU copy),所以,大量的拷贝操作,会成为整个服务的性能瓶颈。 在CProxy中,应用splice的零拷贝计划,数据间接从内核空间的Source Socket Buffer转移到Dest Socket Buffer,不须要任何CPU copy。 splice通过pipe管道“传递”数据,基本原理是通过pipe管道批改source socket buffer和dest socket buffer的物理内存页 ...

March 6, 2022 · 1 min · jiezi

关于c++:C语言带参宏定义和函数的区别

带参数的宏和函数很类似,但有实质上的区别:宏开展仅仅是字符串的替换,不会对表达式进行计算;宏在编译之前就被解决掉了,它没有机会参加编译,也不会占用内存。而函数是一段能够重复使用的代码,会被编译,会给它分配内存,每次调用函数,就是执行这块内存中的代码。 【示例①】用函数计算平方值。 运行后果:1^2 = 12^2 = 43^2 = 94^2 = 165^2 = 25 【示例②】用宏计算平方值。 在 Visual Studio 和 C-Free 下的运行后果(其它编译器的运行后果可能不同,这个++运算的程序无关):3^2 = 15^2 = 97^2 = 25 在示例①中,先把实参 i 传递给形参 y,而后再自增 1,这样每循环一次 i 的值减少 1,所以最终要循环 5 次。 在示例②中,宏调用只是简略的字符串替换,SQ(i++) 会被替换为 ((i++)*(i++)),这样每循环一次 i 的值减少 2,所以最终只循环 3 次。 由此可见,宏和函数只是在模式上类似,实质上是齐全不同的。 带参数的宏也能够用来定义多个语句,在宏调用时,把这些语句又替换到源程序中,请看上面的例子: 运行后果:sa=12, sb=15, sc=20, vv=60

March 5, 2022 · 1 min · jiezi

关于c++:C-重载运算符和重载函数

C++ 容许在同一作用域中的某个函数和运算符指定多个定义,别离称为函数重载和运算符重载。 重载申明是指一个与之前曾经在该作用域内申明过的函数或办法具备雷同名称的申明,然而它们的参数列表和定义(实现)不雷同。 当您调用一个重载函数或重载运算符时,编译器通过把您所应用的参数类型与定义中的参数类型进行比拟,决定选用最合适的定义。抉择最合适的重载函数或重载运算符的过程,称为重载决策。 C++ 中的函数重载在同一个作用域内,能够申明几个性能相似的同名函数,然而这些同名函数的形式参数(指参数的个数、类型或者程序)必须不同。您不能仅通过返回类型的不同来重载函数。 C++ 中的运算符重载您能够重定义或重载大部分 C++ 内置的运算符。这样,您就能应用自定义类型的运算符。 重载的运算符是带有非凡名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号形成的。与其余函数一样,重载运算符有一个返回类型和一个参数列表。 Box operator+(const Box&);申明加法运算符用于把两个 Box 对象相加,返回最终的 Box 对象。大多数的重载运算符可被定义为一般的非成员函数或这被定义为类成员函数。如果咱们定义下面的函数为类的非成员函数,那么咱们须要为每次操作传递两个参数,如下所示: Box operator+(const Box&, const Box&); 可重载运算符/不可重载运算符上面是可重载的运算符列表:

March 5, 2022 · 1 min · jiezi

关于c++:认识-LLVM

简介LLVM是一套提供编译器基础设施的开源我的项目,是用 C++ 编写,蕴含一系列模块化的编译器组件和工具链,用来开发编译器前端和后端。它是为了任意一种编程语言而写成的程序,利用虚构技术发明出编译期间、链接期间、执行期间以及“闲置期间”的优化。 LLVM的命名源自于底层虚拟机(Low Level Virtual Machine)的首字母缩写,导致不理解它的人认为它是相似于 JVM(Java Virtual Machine) 的虚拟机,实际上这个我的项目的范畴并不局限于创立一个虚拟机,而是包含 LLVM 中介码(LLVM IR)、LLVM调试工具、LLVM C++ 规范库等一系列编译工具及低端工具技术的汇合。 传统的动态编译器设计是三阶段设计,其次要组件是前端、优化器和后端。 前端负责词法剖析、语法分析、语义剖析、生成中间代码等性能。 优化器负责进行各种转换以尝试进步代码的运行工夫,例如打消冗余计算,并且通常或多或少独立于语言和指标。 后端(也称为代码生成器)负责将代码映射到指标指令集。除了编写正确的代码外,它还负责生成利用所反对架构的不寻常个性的良好代码。编译器后端的常见局部包含指令抉择、寄存器调配和指令调度。 该模型同样实用于解释器和 JIT 编译器。JVM 也是该模型的一个实现,它应用 Java 字节码作为前端和优化器之间的接口。 而 LLVM 被设计为反对多种源语言或指标架构,它提供了一套适宜编译器零碎的两头语言,如果编译器在其优化器中应用这个两头语言示意,则能够为任何能够编译到它的语言编写前端,并且能够为任何能够从它编译的指标编写后端。 应用这种设计,移植编译器以反对新的源语言只须要实现新的前端,即能够重用现有的优化器和后端;同样想减少反对新的指标架构也只须要实现新的后端。而如果按传统设计,前端和后端理论是耦合在一起,实现新的源语言或反对新的指标架构将须要从头开始,要反对 N 指标和 M 源语言将须要 N*M 个编译器。 LLVM IRLLVM提供了一套适宜编译器零碎的两头语言(Intermediate Representation,IR),有大量变换和优化都围绕其实现,通过变换和优化后的两头语言,能够转换为指标平台相干的汇编语言代码。 该两头语言与具体的语言、指令集、类型零碎无关,其中每条指令都是动态单赋值模式(SSA), 即每个变量只能被赋值一次。这有助于简化变量之间的依赖剖析。 以下是简略的 LLVM IR 代码: define i32 @add1(i32 %a, i32 %b) {entry: %tmp1 = add i32 %a, %b ret i32 %tmp1}define i32 @add2(i32 %a, i32 %b) {entry: %tmp1 = icmp eq i32 %a, 0 br i1 %tmp1, label %done, label %recurserecurse: %tmp2 = sub i32 %a, 1 %tmp3 = add i32 %b, 1 %tmp4 = call i32 @add2(i32 %tmp2, i32 %tmp3) ret i32 %tmp4done: ret i32 %b}上述代码对应的 C 语言代码为: ...

February 26, 2022 · 1 min · jiezi

关于c++:CSE310-堆排序

CSE310 Project 2: Min-HeapIn your second programming project, you will expand your first project. As in the case ofthe first programming project, it should be implemented in C++, on a Linux platform such asgeneral.asu.edu. Your program will be graded on Gradescope, which uses a Linux platform. Youwill continue to have modular design, provide a Makefile to compile various modules to generatethe executable file named run. Among other things, you need to have ...

February 25, 2022 · 7 min · jiezi

关于c++:C并发编程如何调用类内部函数

C11之后,C++引入了多线程规范库thread,这里间接说如何在一个类的成员函数中应用多线程调用起他成员函数的问题。间接上答案。 #include <iostream>#include <thread>using namespace std;class ThreadInClass { public: void threadFun() { cout << "I am a method of ThreadInClass from thread : ." << this_thread::get_id() << endl; } void invokeThreadFun() { thread call(&ThreadInClass::threadFun, ref(*this)); call.join(); }};int main() { ThreadInClass threadClass; threadClass.invokeThreadFun(); return 0;}以上代码中定义了一个ThreadInClass的类,其有两个函数,一个是用来在新的线程中执行的threadFun,一个是在主线程调用的invokeThreadFun,应用是只须要把this指针转换为援用传递给thread的构造函数即可。

February 24, 2022 · 1 min · jiezi

关于c++:CSCI1200数据结构

CSCI-1200 Data StructuresTest 2 — Practice ProblemsNote: This packet contains selected practice problems from Test 2 from three previous years.Your test will contain approximately one third to one half as many problems (totalling ∼100 pts).1 Linked Tube Repair [ / 33 ]Alyssa P. Hacker is working on a modified linked list that is both twodimensionaland circular. A small sample with height=3 and circumference=4is shown below. Each templated Node has pointers to its 4 neighbors. Thetop and bottom edges of the tube structure have NULL pointers. But the leftand right edges wrap around, like a circularly linked list. This cylindrical tubestructure may have any number of nodes for its height and its circumference.template <class T>class Node {public:// REPRESENTATIONT value;Node<T> *up;Node<T> *down;Node<T> *left;Node<T> *right;}; 1.1 Tube repair Diagram [ / 4 ]First Alyssa wants to tackle the challenge of repairing a hole in the structure. Assume a single Node ismissing from the structure, and we have a pointer n to the Node immediately to the left of the hole. Modifythe diagram below to show all of the necessary edits for a call to repair(n,7);nup:1.2 Thinking about Tube repair Complexity [ / 3 ]The repair function should have constant running time in most cases. Describe an example structure witha single missing Node that can be repaired, but not in constant time. Write 2-3 concise and well-writtensentences. You may want to complete the implementation on the next page before answering.11.3 Tube repair Implementation [ / 13 ]Now, implement repair, which takes 2 arguments: a pointer to the Node immediately to the left of thehole and the value to be stored in the hole. You may assume a single Node is missing from the structure.sample solution: 26 line(s) of code21.4 Non-Iterative destroy tube Implementation [ / 13 ]Now write destroy_tube (and any necessary helper functions) to clean up the heap memory associatedwith this structure. The function should take a single argument, a pointer to any Node in the structure.You may assume the structure has no holes or other errors. You cannot use a for or while loop.sample solution: 17 line(s) of code32 Rehashing the Vec Assignment Operator [ / 15 ]Complete the Vec assignment operator implementation below, while minimizing wasted heap memory.Assume the allocator is most efficient when all heap allocations are powers of two (1, 2, 4, 8, 16, etc.)1 template <class T>2 Vec<T>& Vec<T>::operator=(const Vec<T>& v) {3 if (this != &v) {4 delete ;5 m_size = ;6 m_alloc = ;7 m_data = ;8 for (int i = 0; i < ; ++i) {9 m_data[i] = ;10 }11 }12 return *this;13 }Add code below to perform a simple test of the assignment operator:Vec<double> v; v.push_back(3.14159); v.push_back(6.02); v.push_back(2.71828);Is line 12 necessary? Continue your testing code above with a test that would break if line 12 was omitted.What is the purpose of line 3? Write code for a test that would break if lines 3 and 10 were omitted.43 Essay Revision: Embellishment [ / 14 ]Write a function embellish that modifies its single argument, sentence (an STL list of STL strings),adding the word “very” in front of “pretty” and adding “with a wet nose” after “grey puppy”. Forexample:the pretty kitty sat next to a grey puppy in a pretty gardenShould become:the very pretty kitty sat next to a grey puppy with a wet nose in a very pretty gardensample solution: 20 line(s) of codeIf there are w words in the input sentence, what is the worst case Big O Notation for this function? If weswitched each STL list to STL vector in the above function, what is the Big O Notation?STL list: STL vector:54 Essay Revision: Redundant Phrases [ / 15 ]Complete redundant, which takes a sentence and 2 phrases and replaces all occurrences of the first phrasewith the second, shorter phrase. For example “pouring down rain” is replaced with “pouring rain”:it is pouring down rain so take an umbrella → it is pouring rain so take an umbrellaOr we can just eliminate the word “that” (the replacement phrase is empty):I knew that there would be late nights when I decided that CS was the career for me→ I knew there would be late nights when I decided CS was the career for metypedef std::list<std::string> words;void redundant( sentence, phrase, replace) {sample solution: 19 line(s) of code}65 Don’t Ignore Compilation Warnings! [ / 15 ]Write a useful but buggy segment of code (or function) that will compile with no errors but will producethe indicated compilation warning. Put a star next to the line of code that will trigger the warning.Write a concise and well-written sentence describing the intended vs. actual (buggy) behavior of the code.warning: comparison of integers of different signs: 'int' and 'unsigned int'warning: control reaches / may reach end of non-void functionwarning: variable is uninitialized when used here / in this functionwarning: returning reference to local temporary object / reference to stack memoryassociated with a local variable returned7warning: expression result unused / expression has no effectwarning: unused variable / unused parameter6 Cyber Insecurity [ / 5 ]Ben Bitdiddle wrote the following code fragment to manage his personal information.1 std::ifstream istr("my_information.txt");2 std::string s;3 std::vector<std::string> data;4 while (istr >> s) { data.push_back(s); }5 std::vector<std::string>::iterator password = data.begin()+4;6 data.push_back("credit_card:");7 data.push_back("1234-5678-8765-4321");8 data[4] = "qwerty";9 std::cout << "my password is: " << *password << std::endl;my information.txtname: Ben Bitdiddlepassword: pa$$wordSSN: 123-45-6789Write “True” in the box next to each true statement. Leave the boxes next to the false statements empty.Lines 2 & 3 will produce an “uninitialized read” error when run under gdb or lldb.Line 5 is not a valid way to initialize an iterator.Ben’s credit card information is not saved back to the file.This program might behave differently if re-run on this computer or another computer.A memory debugger might detect an “unaddressable access of freed memory” error on Line 9.If we move lines 6 & 7 after line 9, this code fragment will run without memory errors.This code contains memory leaks that can be detected by Dr. Memory or Valgrind.These password choices disqualify Ben from any job in computer security.87 Boxy Storage Solutions [ / 25 ]Eva Lu Ator is working on her capstone project to manage physical storage facilities. She’s mapped outthe overall design and started implementation of the two classes.class Box {public:Box(int w, int d, int h) :width(w), depth(d), height(h) {}int width;int depth;int height;};BwidthdepthheightACStorage storage(4,3,2);assert (storage.available_space() == 24);Box *a = new Box(2,2,2);assert (storage.add(a,0,0,0));Box *b = new Box(3,2,1);assert (!storage.add(b,2,0,0));delete b;Box *b_rotated = new Box(2,3,1);assert (storage.add(b_rotated,2,0,0));Box *c = new Box(1,1,1);assert (storage.add(c,2,0,1));assert (storage.available_space() == 9);class Storage {public:Storage(int w, int d, int h);// FILL IN FOR PART 1bool add(Box *b, int w, int d, int h);int available_space();private:void remove(Box *b, int w, int d, int h);Box **data;int width;int depth;int height;};bool Storage::add (Box *b, int w, int d, int h) {for (int i = w; i < w+b->width; i++) {if (i >= width) return false;for (int j = d; j < d+b->depth; j++) {if (j >= depth) return false;for (int k = h; k < h+b->height; k++) {if (k >= height) return false;if (datai[k] != NULL) return false;}}}for (int i = w; i < w+b->width; i++) {for (int j = d; j < d+b->depth; j++) {for (int k = h; k < h+b->height; k++) {datai[k] = b;}}}return true;}97.1 Missing functions from Storage Class Declaration [ / 5 ]Her friend Ben Bitdiddle doesn’t remember much from Data Structures, but he reminds her that classeswith dynamically-allocated memory need a few key functions. Fill in the missing prototypes for PART 1.7.2 Storage Destructor [ / 20 ]Eva explains to Ben that the private remove member function will be useful in implementing the destructor.First write the remove member function:sample solution: 10 line(s) of codeNow write the Storage class destructor:sample solution: 14 line(s) of code108 Transpose Linked Grid [ / 27 ]Louis B. Reasoner is working on a new member function for our Homework 5 Linked Grid named transpose.This function should mirror or flip the elements along the diagonal. Here’s a sample grid with integer dataand how it prints before and after a call to transpose:grid.print();std::cout << std::endl;grid.transpose();grid.print();1 2 3 48 7 6 59 10 11 121 8 92 7 103 6 114 5 12template <class T>class Node {public:// REPRESENTATIONT value;Node<T> *up;Node<T> *down;Node<T> *left;Node<T> *right;}; 8.1 Diagram [ / 7 ]First neatly modify the diagram of this smaller grid below to show all of the necessary edits that must beperformed by a call to transpose().:upper_leftup:down:right:value::leftup:down:right:value::leftup:down:right:value::leftup:down:right:value::leftup:down:right:value::leftup:down:right:value::leftheight:upper_right:width::lower_left lower_left:Grid<int>NULLNULL NULL NULLNULLNULLNULL NULL NULLNULL4 5 61 2 33 28.2 Complexity Analysis [ / 5 ]What is the Big ’O’ Notation for the running time of the transpose() member function? Assume the gridwidth is w and the height is h. Write 1-2 concise and well-written sentences justifying your answer. Youprobably want to complete the implementation on the next page before answering.118.3 Implementation [ / 15 ]Louis has suggested that we first implement a helper non-member function named swap, which will makethe implementation of transpose more concise.sample solution: 5 line(s) of codeNow implement transpose, as it would appear outside of the Grid class declaration.sample solution: 16 line(s) of code129 Organizing Words [ / 30 ]Alyssa P. Hacker is working on a program to clean up a dataset of words. The task is to write a functionnamed organize_words that takes in an STL vector of STL lists of words (STL strings). The functionshould organize the words into groups by word length, and ensure that the words are sorted within eachgroup. Many or most of the words will already be in the right place. That is, they will already be in theslot of the vector that matches the length of the word. And the neighboring words in each slot/list willalready be mostly alphabetized.For example, given the data shown on the left, your implementation should move the four misplaced wordsto produce the data shown on the right.01 diamond23 gem malachite4 jade opal rock ruby5 geode pearl talc stone topaz6 garnet quartz gypsum7 amethyst azurite emerald8 fluorite sapphire90123 gem4 jade opal rock ruby talc5 geode pearl stone topaz6 garnet gypsum quartz7 azurite diamond emerald8 amethyst fluorite sapphire9 malachiteTo make the problem a little more “fun”, you are NOT ALLOWED to use:• the STL vector subscript/indexing operator, [ ], or .at(),• the STL sort function, or• any of the push or pop functions on vector or list.You may assume that the initial vector has at least as many slots as the longest word in the structure.9.1 Complexity Analysis - Big ’O’ Notation [ / 6 ]Once you’ve finished your implementation on the next pages, analyze the running time of your solution.Assume there are w total words in the whole structure, v slots in the vector, a maximum of m wordsper list, and x words are misplaced and need to be moved. Write 2-3 concise and well-written sentencesjustifying your answer.139.2 Helper Function Implementation [ / 12 ]Alyssa suggests writing a helper function named place that will place a word in the correct location in thestructure. Work within the provided framework below. Do not add any additional for or while loops.void place( ) {sample solution: 2 line(s) of codewhile ( ) {sample solution: 3 line(s) of codewhile ( ) {sample solution: 5 line(s) of code}sample solution: 5 line(s) of code}}149.3 Organize Implementation [ / 12 ]And now write the organize function, which calls the place function. Again, work within the providedframework below and do not add any additional for or while loops.void organize_words( ) {sample solution: 2 line(s) of codewhile ( ) {sample solution: 2 line(s) of codewhile ( ) {sample solution: 8 line(s) of code}sample solution: 2 line(s) of code}}1510 Merge-Spiration: Recursive Interval Computation [ / 15 ]Ben Bitdiddle was inspired by the recursive merge sort examplefrom Data Structures lecture and proposes it as a guide to computethe smallest interval that contains a collection of floating pointnumbers (e.g., the minimum and maximum). Implement Ben’s idea,a recursive function named compute interval that takes in an STLvector of floats and returns an Interval object.For example: 6.2 4.3 10.4 2.5 8.4 1.5 3.7 → [1.5, 10.4]class Interval {public:Interval(float i, float j): min(i), max(j) {}float min;float max;};sample solution: 12 line(s) of codeWithout resorting to personal insults, explain in two or three concise and well-written sentences why Ben’sidea isn’t going to result in significant performance improvements. Be technical.1611 How many DS students to change a lightbulb? [ / 38 ]In this problem you will complete the implementation of two new classes named Bulb and Lamp. We beginwith an example of how these classes are used.First, we create a new lamp that will hold 3 bulbs and make a note of the manufacturer’s recommendedbulb: a 60 watt bulb with an estimated lifetime of 300 hours from Phillips. Note that initially this lamphas no bulbs installed. We install one of manufacturer’s recommended bulbs and use the lamp (turn it“on”) for a total of 50 hours.Lamp floorlamp(Bulb(60,300,"Phillips"),3);bool success;success = floorlamp.install(); assert(success);floorlamp.On(50);assert (floorlamp.getTotalWattage() == 60);Next, we attempt to install 3 bulbs, another of the manufacturer’s recommended bulbs, and then two otherbrands of bulbs. The installation of the 3rd bulb made by Sylvania fails because there are no availablesockets slots in the lamp and no bulbs are burnt out and need replacement.success = floorlamp.install(); assert(success);success = floorlamp.install(Bulb(40,120,"GE")); assert(success);success = floorlamp.install(Bulb(120,500,"Sylvania")); assert(!success);We then use the lamp for another 100 hours. Once the wattage drops (due to a burnt out bulb), we againtry to install the Sylvania bulb and it is successful.floorlamp.On(100);assert (floorlamp.getTotalWattage() == 160);floorlamp.On(50);assert (floorlamp.getTotalWattage() == 120);success = floorlamp.install(Bulb(120,500,"Sylvania")); assert(success);assert (floorlamp.getTotalWattage() == 240);Finally, we create a duplicate lamp. Note that when we do this, we match the bulbs currently installed inthe original lamp, but the bulbs installed in the new lamp are brand new (and unused).Lamp another(floorlamp);assert (floorlamp.getTotalWattage() == another.getTotalWattage());for (int i = 0; i < 10; i++) {floorlamp.On(50);another.On(50);std::cout << "compare " << floorlamp.getTotalWattage() << " "<< another.getTotalWattage() << std::endl;}Which results in this output:compare 240 240compare 240 240compare 180 240compare 120 240compare 120 240compare 120 240compare 120 120compare 120 120compare 120 120compare 120 12011.1 Bulb Class Declaration [ / 14 ]The Bulb class is missing only one function. You will need to read the rest of the problem to determine what’smissing. Fill in the missing function – implement the function right here, within the class declaration.17class Bulb {public:// constructorsBulb(int w, int l, const std::string &b) :wattage(w),lifetime(l),hours_used(0),brand(b) {}sample solution: 2 line(s) of code// accessorsint getWattage() const { return wattage; }bool burntOut() const { return hours_used > lifetime; }const std::string& getBrand() const { return brand; }// modifiervoid On(int h) { hours_used += h; }private:// representationint wattage;int lifetime;int hours_used;std::string brand;};11.2 Lamp Class Declaration [ / 14 ]The Lamp class has a few more missing pieces. Read through the rest of the problem before attempting to fillthis in. Write the prototypes (not the implementation!) for the four missing functions. You will implementsome of these missing functions later. Also, fill in the member variables for the Lamp representation.Important: You may not use STL vector on this problem.class Lamp {public:// constructors, assignment operator, destructorsample solution: 4 line(s) of code18// accessorint getTotalWattage() const;// modifiersbool install(const Bulb &b = Bulb(0,0,""));void On(int h);private:// representationsample solution: 3 line(s) of code};Lamp Class ImplementationHere’s the implementation of one of the key member functions of the Lamp class.bool Lamp::install(const Bulb &b) {// first, let's figure out where to install the bulbint which = -1;for (int i = 0; i < max_bulbs; i++) {// check for an empty socketif (installed[i] == NULL) {which = i;break;}// or a socket that contains a burnt out bulbif (installed[i]->burntOut()) {which = i;delete installed[i];break;}}// return false if we cannot install this bulbif (which == -1) return false;if (b.getWattage() == 0) {// install the manufacturer's recommended bulb typeinstalled[which] = new Bulb(recommended);} else {// install the specified bulbinstalled[which] = new Bulb(b);}return true;}On the last two pages of this problem you will implement three important functions for the Lamp class, asthey would appear outside of the class declaration (in the lamp.cpp file) because their implementationsare > 1 line of code.1911.3 Lamp Constructor [ / 9 ]sample solution: 7 line(s) of code11.4 Lamp Destructor [ / 5 ]sample solution: 8 line(s) of code2011.5 Lamp Assignment Operator [ / 9 ]sample solution: 10 line(s) of code2112 Singly Linked List Subsequence Sum [ / 18 ]Write a recursive function named FindSumStart that takes the head Node of asingly-linked list storing positive numbers. The function should return a pointerto the Node that begins a subsequence of numbers that ends in the sum of thatsubsequence. For example, given this sequence: 5 1 4 2 3 9 6 7 the functionshould return a pointer to the Node storing 4, because 4 + 2 + 3 = 9.template <class T>class Node {public:Node(const T& v): value(v),next(NULL) {}T value;Node* next;};sample solution: 15 line(s) of codeAssuming the sequence has n numbers, what is the order notation for the running time of your function?2213 Reverse Splice [ / 20 ]Write a function named reverse_splice that takes in 3 arguments: an STL list named data and twoiterators i and j. The function should reverse the order of the data between those iterators. For example,if data initially stores this sequence: 1 2 3 4 5 6 7 8 9 and i refers to 3 and j refers to 7, then afterthe call reverse_splice(data,i,j), data will contain: 1 2 7 6 5 4 3 8 9 , i will refer to element 7,and j will refer to element 3. Your function should return true if the operation was successful, and false ifthe request is invalid. Note: Your function may only use a constant amount of additional memory.sample solution: 21 line(s) of code2314 Doubly Linked Factorization [ / 17 ]class Node {public:Node(int v) :value(v),next(NULL),prev(NULL) {}int value;Node* next;Node* prev;};Write a recursive function named Factor that takes in two arguments, pointers to the head and tail Nodesof a doubly linked list. This function should look for a non-prime number in the linked list structure, breakthe Node into two Nodes storing two of its factors, and then return true. If all elements are prime thefunction returns false. For example, if we start with a 3 element list containing 35 30 28 and repeatedlycall Factor:PrintNodes(head);while (Factor(head,tail)) { PrintNodes(head); }This is the output:35 30 285 7 30 285 7 2 15 285 7 2 3 5 285 7 2 3 5 2 145 7 2 3 5 2 2 75 7 2 3 5 2 2 7You may write a helper function. You do not need to write the PrintNodes function. ...

February 18, 2022 · 15 min · jiezi

关于c++:CMDA-3634-图像处理

CMDA 3634 SP2020 The Wave Equation with C Project 02Project 02: The Wave Equation with CVersion: Current as of 2021-02-27 11:01:25Due:– Preparation: 2021-02-27 23:59:00– Coding & Analysis: 2021-03-12 23:59:00 (24 hour grace period applies to this due date.)Points: 100Deliverables:– Preparation work as a PDF, typeset with LaTeX, through Canvas.– All code through code.vt.edu, including all LaTeX source.– Project report and analysis as a PDF, typeset with LaTeX, through Canvas.Collaboration:– This assignment is to be completed by yourself.– For conceptual aspects of this assignment, you may seek assistance from your classmates. In your submissionyou must indicate from whom you received assistance.– You may not assist or seek assistance from your classmates on matters of programming, code design, orderivations.– If you are unsure, ask course staff.Honor Code: By submitting this assignment, you acknowledge that you have adhered to the Virginia TechHonor Code and attest to the following:I have neither given nor received unauthorized assistance on this assignment. The work I am presentingis ultimately my own.References C:– Introduction to C https://www.cprogramming.com/... The Wave Equation:– General overview https://en.wikipedia.org/wiki... https://mathworld.wolfram.com... OpenStax: Mathematics of Waves (link)– Standing Waves (especially in 2D with a rectangular boundary) https://en.wikipedia.org/wiki...– Chapter 5.1 of Gilbert Strang’s course notes “5.1 Finite Difference Methods” https://math.mit.edu/classes/...– Chapter 5.3 of Gilbert Strang’s course notes “5.3 The Wave Equation and Staggered Leapfrog” https://math.mit.edu/classes/... LaTeX:– Writing pseudo-code in Latex: https://en.wikibooks.org/wiki...– General topics: https://www.overleaf.com/learn1CMDA 3634 SP2020 The Wave Equation with C Project 02Code Environment For this project, use a terminal-based programming environment.– Use a terminal-based editor such as Vim, Emacs, or nano.– Compile your project from the terminal with make.– In particular, do NOT use IDEs such as Visual Studio or Eclipse. All necessary code must be put in your class Git repository. Your Git repository must have the following structure:cmda3634/projects/proj02/code/data/report/ Data and any scripts which are necessary to recreate your data, must be in the data directory.DO NOT INCLUDE LARGE NUMBERS OF IMAGE FILES OR LARGE VIDEO FILES IN YOURGIT REPOSITORY! Your tex source for project preparation and final report go in the report directory. Remember: commit early, commit often, commit after minor changes, commit after major changes. Pushyour code to code.vt.edu frequently. You must separate headers, source, and applications. You must include a makefile. You must include a README explaining how to build and run your programs.2CMDA 3634 SP2020 The Wave Equation with C Project 02RequirementsPreparation (20%) ...

February 17, 2022 · 11 min · jiezi

关于c++:PIC-10B-解析

PIC 10B Homework 5 Due Wednesday, March 10Problem 1:Using good coding practices, design your own Linked List of int types. It will consistof classes List, Node, and Iterator granting friendship and defining functions as needed.Write constructors, destructors, and all necessary member functions such as insert, erase,increment and decrement operators, operator* to dereference, as well as operator== andoperator!= to check whether two iterators are pointing to the same element. You will thenuse this list to write the following member functions:(1) List::reverse to reverse your nodes(2) List::push front to add a value to the beginning of a list(3) List::sort to sort the elements of a linked list (without copying them into a vector oranother data type)(4) List::merge which accepts another List object and merges the two lists into one, alternatingelements from each list such that merging 1 7 12 and 8 3 11 2 2 1 yields the list 18 7 3 12 11 2 2 1.Write a main function to test your list such that it follows the output shown in Figure 1.Figure 1: sample output.Due Wednesday, March 10 Homework 5 PIC 10BGood Coding Practices:• think about cross-platform. Don’t use Windows or Mac only commands. For example,pause == cin.get() twice, write many \n vs. system(clear) or system(’cls).• passing objects by reference & or const & when possible• using field initializer list when possible in all constructorsInstructions for submission:• Name your files exactly hw5.cpp, List.h, List.cpp, Node.h, Node.cpp, Iterator.h,and Iterator.cpp.• You may not use #include "stdafx.h".• Add code description in the comment at the beginning of the file.A sample description may look like:/*PIC 10B 2A, Homework 1Purpose: Tic-tac-toe gameDate: 10/10/2019*/• Submit your header files and source codes to CCLE in separate files. Only .h and .cppfiles should be uploaded. ...

February 17, 2022 · 2 min · jiezi

关于c++:深入理解C对象模型开始由virtual继承说起

0 引言最近在工作之余,从新拾起了深度摸索C++对象模型 这本书,想要进一步温习了解 C++对象模型相干的原理。 以往看这本书,仅仅是浮于外表,并没有入手去实现和验证书中所说的内容。因而这次,便想既然再度学习,那么就深刻去看一看目前风行的编译器对C++对象模型 是如何实现的。故有了本专题。 目前应用较宽泛的编译器有gcc,clang, msvc,但作为C++后盾开发置信应用gcc,clang较多,而我也是应用两者较多,因而 本专题中以gcc编译器为主,次要深入研究其对C++对象模型的实现。 如果你感觉深度摸索C++对象模型 让你深入了内力,想要进一步摸索古代编译器对其的实现,进一步加深相应的了解,那心愿本专题会对你有所帮忙。 学习本专题,须要你先学习深刻了解计算机系统(原书第3版) 次要相熟 ATT汇编,根本的函数调用规定等, 同时也须要你学习了深度摸索C++对象模型 这本书,毕竟,本专题以此书为主。 此外,你须要相熟GDB, 特地是如下几个命令, 具体的解说 可参考后续链接局部 set print pretty onset print vtbl onset print object on也心愿你能常常应用如下两个在线工具: https://cppinsights.io/ godblot 本专题所应用的机器环境如下 uname -aLinux qls-VirtualBox 5.11.0-38-generic #42~20.04.1-Ubuntu SMP Tue Sep 28 20:41:07 UTC 2021 x86_64 x86_64 x86_64 GNU/Linuxgcc编译器版本为 gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)最初,自己也只是因为趣味而想进一步钻研,两头可能会有些了解不对的中央,欢送大家随时斧正;同时因为工作比较忙,因而我可能会断断续续更新该专栏。 1 故事的开始对于C++对象模型,咱们以深度摸索C++对象模型 第三章开篇所给的例子说起,其例子如下 #include <iostream>#include <string>class X {};class Y : public virtual X {};class Z : public virtual X {};class A : public Y, public Z {};int main() { std::cout << "sizeof(X): " << sizeof(X) << "\n"; std::cout << "sizeof(Y): " << sizeof(Y) << "\n"; std::cout << "sizeof(Z): " << sizeof(Z) << "\n"; std::cout << "sizeof(A): " << sizeof(A) << "\n"; return 0;}上述例子很简略,通过我的试验,在我的环境下上述输入的后果为 ...

February 16, 2022 · 2 min · jiezi

关于c++:Comp-218EC-面向对象编程

Concordia UniversityComp 218/EC – Winter 2021Fundamentals of Object Oriented ProgrammingAssignment 2__Deadline: By 11:59pm Friday March 12th , 2021.Evaluation: 2.5 % of your final gradeLate Submission: Late assignments will be discounted by 25%. Late assignments are accepted up to 5days late (grace period) and weekends count.Teams: The assignment is to be done individually.Purpose: The purpose of this assignment is to have you experience the basic steps involved inwriting a complete C++ program (from algorithm development to coding) and topractice with string data type variables, selection statements and the whilerepetition statement.General Guidelines When Writing Programs:Same as for assignment #1 – Refer to assignment #1 handout for details.RECOMMENDATION for this Assignment:Take the time to write out an algorithm for these problems to help clarify the logic BEFORE you startprogramming. (No need to hand in the algorithm.)Question #1: Speed System Program (6 pts)In this question, you will write a program that determines the penalty of a driver who is speeding onhighway with the speed limit of 100km/h based on Ontario Courts.Your program should follow the following rules:• Prompt the user to enter name, id and score and validates the information.• The student name should be entered as “LastName, FirstName” (separated by comma).Please note the whole name should be saved in one string.• The driver ID must have 7 digits.• The driver’s SPEED must greater than 0.• If the user enter correct information, your program should display the fine based on thespeed. When the fine is displayed, the output should be“FirstName LastName got SPEED. Based on the speed system, FirstName (ID) will pay X.”Please note the calculation of X is based on the following rules: ...

February 16, 2022 · 5 min · jiezi

关于c++:Leetcode专题数组163缺失的区间

力扣链接:https://leetcode-cn.com/probl...解题思路: 这道题整体上自身比较简单,然而要解决的边界条件绝对比拟多数组是排序的,那么在[lower, upper]这个区间中,如果没有缺失数字/区间的话,实践上每个数字都应该是相邻的,那么就能够从lower做为终点,顺次进行遍历,如果数组中的数字大于lower开始的游标(每次比拟完lower加一),那么就阐明有缺失,此时的缺失能够分为两种状况:(1)只缺失了一个数字,那么lower就等于nums[i] - 1 (2)缺失多个数字:lower 就小于nums[i] - 1.最初整个数组遍历完结之后,游标此刻指向数组最初一个数+1,然而upper不肯定和最初一个数相等,也有可能大于最初一个数字,那么这个时候就须要比拟游标和upper的大小,如果相等则将upper退出,如果upper大于l,那么退出l->upperclass Solution {public: vector<string> findMissingRanges(vector<int>& nums, int lower, int upper) { long l = lower; vector<string> ans; for(int i = 0; i < nums.size(); ++i) { if(l == nums[i]) l++;//相等,我跳过你 else if(l < nums[i]) { //有空缺 if(l < nums[i]-1)//大于1 ans.push_back(to_string(l)+"->"+to_string(nums[i]-1)); else if(l == nums[i]-1)//等于1 ans.push_back(to_string(l)); l = long(nums[i])+1;//更新l到nums[i]下一个数 // [2147483647] // 0 // 2147483647 } } if(l < upper) ans.push_back(to_string(l)+"->"+to_string(upper)); else if(l==upper) ans.push_back(to_string(l)); return ans; }};

February 15, 2022 · 1 min · jiezi

关于c++:2022-技术趋势报告C-重新受宠-dataPythonJava上榜热搜词-安全话题备受关注

近日,O'Reilly 出炉了“2022 技术趋势”报告。该报告数据展现了以后在 AI 技术推动下为行业带来的微小转变,让咱们对接下来新技术趋势带来的全新思维形式及其意义,以及将来塑造软件开发和软件架构的大变动有了进一步理解。 该报告通过对 2021 年 1 月 - 9 月的四种特定类型的数据进行了钻研(搜寻查问、向 O’Reilly Answers 提出的问题、按 title 列出的资源应用状况、按主题分类法列出的资源应用状况),并将其与 2020 年前 9 个月的数据行比照后最终得出了乏味的论断。 报告结果显示,随着勒索软件的“流行”,“data”数据及平安话题正成为开发者关注的焦点,而 IoT 及游戏开发的衰亡则从新激发了开发者对 C++ 编程语言的趣味。同时 Go 和 Rust 等较新的语言倒退迅猛,也正在“威逼”着 C 语言的位置。 热搜词: “data”、“Python”、“Java”上榜一个令人诧异的景象是,很多用户会抉择间接从题库里将问题输出 O’Reilly Answers (该平台的搜索引擎)搜寻栏。这也很好的解释了为什么 O’Reilly Answers 外面常常会呈现一些高频热搜问题。 比方“什么是动静布局?(What is dynamic programming?)”这个问题就会经常出现在题库中。当然,这个问题仅次于“如何编写好的单元测试用例?(How do I write good unit test cases?)”该问题在题库中也很热门。 该热搜数据显示,“data”数据依然是用户最关注的重要话题之一。热搜词前五的单词别离是:“data”、“Python”、“Git”、“test”和“Java”(能在下面两个热门问题里看到热搜词top 15 / 20 里的大部分单词。)而与“数据”一词最常呈现的词组是“数据治理”(其次是“数据迷信”“数据分析”和“数据工程”),看得出,“数据治理”将会是接下来值得关注的话题。 另外,Python 和 Java 仍旧是该平台上的两大编程语言,不过此次数据显示往年对于 Python 和 Java 的内容使用率略有降落,而对于 Rust 和 Go 的内容使用率正在快速增长(只管绝对较小)。 ...

February 7, 2022 · 1 min · jiezi

关于c++:动态创建二维数组

本文基于《数据结构、算法与利用 C++语言形容》一书。创立二维数组 template<class T>void make2dArray(T ** &a, int numberOfRows, int numberOfColumns){ // 创立行指针 a = new T * [numberOfRows]; // 为每一行调配空间 for(int i = 0; i < numberOfRows; i++) a[i] = new T[numberOfColumns];}删除二维数组 template<class T>void delete2dArray(T ** &a, int numberOfRows){ // 删除行数组空间 for(int i = 0; i < numberOfRows; i++) delete [] a[i]; // 删除行指针 delete [] a; a = NULL;}残缺代码 #include <iostream>using namespace std;/* 创立二维数组*/template<class T>void make2dArray(T ** &a, int numberOfRows, int numberOfColumns){ // 创立行指针 a = new T * [numberOfRows]; // 为每一行调配空间 for(int i = 0; i < numberOfRows; i++) a[i] = new T[numberOfColumns];}/* 删除二维数组*/template<class T>void delete2dArray(T ** &a, int numberOfRows){ // 删除行数组空间 for(int i = 0; i < numberOfRows; i++) delete [] a[i]; // 删除行指针 delete [] a; a = NULL;}/* 初始化数组为全0*/template<class T>void initArray(T ** &a, int numberOfRows, int numberOfColumns){ for(int i = 0; i < numberOfRows; i++) for(int j = 0; j < numberOfColumns; j++) a[i][j] = 0;}/* 打印数组内容*/template<class T>void printArray(T ** &a, int numberOfRows, int numberOfColumns){ for(int i = 0; i < numberOfRows; i++) { for(int j = 0; j < numberOfColumns; j++) cout << a[i][j] << " "; cout << "\n"; }}int main(){ int **a; try { int rows, columns; rows = 3; columns = 4; make2dArray(a, rows, columns); initArray(a, rows, columns); a[1][2] = 1; printArray(a, rows, columns); delete2dArray(a, rows); } catch(bad_alloc &e) { cerr << "Could not create two-dimensional array a\n"; cerr << "bad_alloc capture: " << e.what() << "\n"; } system("pause"); return 0;}后果 ...

January 30, 2022 · 2 min · jiezi

关于c++:模板函数中以引用的方式传递数组

本文基于《数据结构、算法与利用C++语言形容》一书。其中,在第一章的练习2中,有一个题目是这样形容的: 编写一个模板函数 count,返回值是数组 a[0:n-1] 中 value 呈现的次数。测试你的代码。书中给出的代码是这样的: template<class T>T count(T a[], int n, const T& value){ int theCount = 0; for(int i = 0; i < n; i++) if(a[i] == value) theCount++; return theCount;}然而出于好奇想要尝试一下以援用的形式去传递这个数组,于是有 template<class T, int n>T count(T (&a)[n], const T& value){ int i, t; t = 0; // t -> time for(i = 0; i < n; i++) if(a[i] == value) ++t; return t;}残缺代码 #include <iostream>#include <iterator>using namespace std;template<class T, int n>T count(T (&a)[n], const T& value){ int i, t; t = 0; // t -> time for(i = 0; i < n; i++) if(a[i] == value) ++t; return t;}int main(){ int a[6] = {1, 2, 3, 4, 1, 1}; cout << "a[0:5] = "; copy(a, a+6, ostream_iterator<int>(cout, " ")); cout << "\n"; cout << "count(a, 1) = " << count(a, 1) << "\n"; cout << "count(a, 2) = " << count(a, 2) << "\n"; system("pause"); return 0;}后果 ...

January 29, 2022 · 1 min · jiezi

关于c++:现代C设计魅力虚函数继承thunk技术初探

简介:工作中应用LLDB调试器调试这一段C++多继承程序的时候,发现通过lldb print(expression命令的别名) 命令获取的指针地址和理论了解的C++的内存模型的地址不一样。那么到底是什么起因呢? 作者 | 扬阜起源 | 阿里技术公众号 一 问题背景1 实际验证工作中应用LLDB调试器调试这一段C++多继承程序的时候,发现通过lldb print(expression命令的别名) 命令获取的指针地址和理论了解的C++的内存模型的地址不一样。那么到底是什么起因呢?程序如下: class Base {public: Base(){}protected: float x;};class VBase {public: VBase(){} virtual void test(){}; virtual void foo(){};protected: float x;};class VBaseA: public VBase {public: VBaseA(){} virtual void test(){} virtual void foo(){};protected: float x;};class VBaseB: public VBase {public: VBaseB(){} virtual void test(){ printf("test \n"); } virtual void foo(){};protected: float x;};class VDerived : public VBaseA, public Base, public VBaseB {public: VDerived(){} virtual void test(){} virtual void foo(){};protected: float x;};int main(int argc, char *argv[]){ VDerived *pDerived = new VDerived(); //0x0000000103407f30 Base *pBase = (Base*)pDerived; //0x0000000103407f40 VBaseA *pvBaseA = static_cast< VBaseA*>(pDerived);//0x0000000103407f30 VBaseB *pvBaseB = static_cast< VBaseB*>(pDerived);//0x0000000103407f30 这里应该为0x0000000103407f48,然而显示的是0x0000000103407f30 unsigned long pBaseAddressbase = (unsigned long)pBase; unsigned long pvBaseAAddressbase = (unsigned long)pvBaseA; unsigned long pvBaseBAddressbase = (unsigned long)pvBaseB; pvBaseB->test();}通过lldb print命令获取的地址如下图: ...

January 29, 2022 · 10 min · jiezi

关于c++:多视角三维模型纹理映射-02

前言通过前篇文章《多视角三维模型纹理映射 01》,根本对OpenMVS框架和应用办法有了一个简略的了解,这里持续基于上一篇文章进行本人的探索,也对上篇文章中留下的问题进行解释。 已知: 1、手头有从8个角度拍摄的点云数据,且点云曾经通过配准、交融、网格化造成了Mesh; 2、8个点云的外参(确认正确无误); 3、8个角度的图片; 原始点云是这样的: 点云配准后如上篇文章《G2O与多视角点云全局配准优化》图片所示。 实现基于OpenMVS,次要实现代码片段如下: void texture() { int number_of_thread = 1; Scene scene(number_of_thread); Eigen::Matrix4d temp; std::string t_inPath = "./test/scene/1_in.txt"; loadMat4(t_inPath, temp); Eigen::Matrix3d _k = temp.block<3, 3>(0, 0); //相机内参 //归一化 _k(0, 0) = _k(0, 0) / 1600; _k(1, 1) = _k(1, 1) / 1600; _k(0, 2) = _k(0, 2) / 1600; _k(1, 2) = _k(1, 2) / 1600; { //填充platform Platform &plat = scene.platforms.AddEmpty(); //1、name plat.name = "platform"; CameraIntern &cam = plat.cameras.AddEmpty(); cam.R = RMatrix::IDENTITY; cam.C = Point3(0, 0, 0); cam.K = _k; //已知 有8个相机位姿 std::string matrix_path = "./test/scene/"; for (int i = 1; i <= vieNum; ++i) { std::string _path = matrix_path + std::to_string(i) + "_ex.txt"; Eigen::Matrix4d temp; loadMat4(_path, temp); Platform::Pose &pose = plat.poses.AddEmpty(); pose.C = temp.block<3, 1>(0, 3); pose.R = temp.block<3, 3>(0, 0); } } {//填充images std::string imag_path = "test/image/"; std::string matrix_path = "test/scene/"; //ImageArr imgarr = scene.images; for (int i = 1; i <= vieNum; ++i) { std::string t_img = imag_path + std::to_string(i) + ".jpg"; String _imgP(t_img); Image &_img = scene.images.AddEmpty(); _img.ID = i-1; _img.platformID = 0; _img.cameraID = 0; _img.poseID = i-1; _img.LoadImage(_imgP); scene.images.push_back(_img); } } scene.mesh.Load("test/sm_mesh.ply"); unsigned nResolutionLevel = 0; unsigned nMinResolution = 1280; float fOutlierThreshold = 0.f; float fRatioDataSmoothness = 0.0f; bool bGlobalSeamLeveling = true; bool bLocalSeamLeveling = true; unsigned nTextureSizeMultiple = 0; unsigned nRectPackingHeuristic = 0; bool res = scene.TextureMesh(nResolutionLevel, nMinResolution, fOutlierThreshold, fRatioDataSmoothness, bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic); std::cout << "texture res:" << res << std::endl; //scene.Save("./test/res_tex.mvs",ARCHIVE_TEXT); scene.mesh.Save("test/res_tex.ply");}依照上篇文章《多视角三维模型纹理映射 01》中所述,须要填充Scene中的相干数据成员。在这里我增加了一个Platform以及一个camera,而后增加了8个相机的Pose,这是合乎本人的理论应用状况的,我有一个相机,拍摄了指标的8个角度的图像,所以我只有一个平台,一个相机,然而复原了8个相机的位姿。 ...

January 26, 2022 · 2 min · jiezi

关于c++:多视角三维模型纹理映射-01

本片文章算是作为上一篇文章【G2O与多视角点云全局配准优化】 的连续。从上篇文章杠已知,当初目前手头曾经有了配准好的全局点云、每块点云的变换矩阵以及对应每块点云的RGB图像。接下来,自然而然的便是:对全局点云重建三维网格,并对重建后的三维网格进行纹理贴图。已知:三维模型(三角面片,格局任意),多视角RGB图片(纹理)、变换矩阵;求:为三维模型贴上纹理图。针对上述待求解纹理,相熟的小伙伴必定直到,其实在求解多视角立体匹配的最初一步--外表重建与纹理生成。接上篇,为实现本人的目标,首先须要重构三角网格,从点云重建三角网格,与相机、纹理图片等没有任何关系,可间接应用pcl中的重建接口或者cgal甚至meshlab等软件,间接由三维点云重建三角网格。在实现重建三角网格之前,还有很重要--然而能够酌情省略的一个关键步骤:多视角三维点云交融!上面持续应用本人之前所拍摄的8个点云片段为例进行示例记录。(留神,此处强调8个点云片段,并不示意8个视角的点云,后续阐明)。 多视角点云交融将多个点云片段拼接之后,无奈防止的存在多个视角下点云互相重叠的状况。如下图所示,在重叠区域的点云疏密水平个别都大于非重叠区域点云。进行点云交融的目标一是为了点云去重,升高点云数据量;二是为了进一步平滑点云,进步精度,为后续的其余计算(如测量等)提供高质量的数据。 凑巧,本人对挪动最小二乘算法有肯定理解,在pcl中,N年之前【pcl之MLS平滑】和【pcl之MLS算法计算并对立法向量】也做过一些小测试。在我的印象中,挪动最小二乘是这样工作的:针对深刻数据,计算指标点及其邻域,这些待计算的部分数据便形成了指标点的紧支域,在紧支域内有某个函数对指标点进行运算,运算的根本规定是根据紧支域内其余点到指标点的权重不同,这里的某个函数即所谓的紧支函数。紧支函数 + 紧支域 +权重函数形成了挪动最小二乘算法的根本数学概念,所谓移动性则体现在紧支域在容许的空间中“滑动”计算,直至笼罩所有数据。最小二乘个别针对全局求最优,而挪动最小二乘因为其 “移动性”(紧支)不仅能针对全局优化求解,而且也具备局部优化性,更进一步的,针对三维点云,其可能提取等值面,联合MC(挪动立方体)算法,实现外表三角网格的重建。 pcl中,对于MLS算法的例子很多很多,本人之前的两篇水文也算也有个根本的利用介绍,此处不在过多记录。在这里,间接应用如下代码: pcl::PointCloud<pcl::PointXYZRGB> mls_points; //存后果pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>);pcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGB> mls;mls.setComputeNormals(false);mls.setInputCloud(res);mls.setPolynomialOrder(2); //MLS拟合的阶数,mls.setSearchMethod(tree);mls.setSearchRadius(3);mls.setUpsamplingMethod(pcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGB>::UpsamplingMethod::VOXEL_GRID_DILATION);mls.setDilationIterations(0); //设置VOXEL_GRID_DILATION办法的迭代次数mls.process(mls_points);留神,上述计算过程中,应用了pcl::MovingLeastSquares::VOXEL_GRID_DILATION办法,依照pcl官网解释,该办法不仅可能修复大量点云空洞,而且可能对点云坐标进行局部优化,输入为全局疏密水平一样的点云,通过设置不同的迭代次数,该办法不仅可能降采样,还能上采样(次要通过迭代次数管制). 将本人的数据放入上述计算过程,点云交融部分成果如下: 肉眼可见点云更加平均、平滑,同同时数据量从100w+ 降到 10w+. 上述操作,根本满足了本人下一步的要求。 进一步的,鉴于外表重建并非重点,针对上述后果,这里间接应用MeshLab软件中的泊松重建,后果记录如下: 多视角纹理映射在这里,正式引入本人对所谓“多视角”的了解。 首先,多视角与多角度,通常状况下,这两个概念根本都是在说同一件事件,即从不同方位角拍摄三维模型。然而这其中又隐含两种不同的 [操作形式],其一如手持式三维扫描仪、SLAM中的状态预计、甚至搭载摄像机/雷达的主动驾驶汽车等,这些场景下根本都是相机在动,指标不动,即相机绕指标静止;其二 如转台式三维扫描仪等,这些场景根本都是相机不动,指标动,即指标自身具备静止属性。所以这里,有必要对多视角与多角度做进一步的辨别,多视角指的是相机的多视角(对呀,相机才具备实在的物理视角、位姿、拍摄角度 巴拉巴拉...),多角度指的是指标物体的不同角度(对呀,一个物体能够从不同的角度被察看)。 其次,外参,外参是很重要的一个概念(废话,还用你说!),可真的引起其余使用者足够的器重吗?未必! 咱们个别常说的外参,其实是带有主语的,只是咱们太司空见惯从而把主语省略了。外参---个别指相机的外参,即形容相机的变动。在多视角三维点云配准中,每个点云都有一个变动矩阵,该变动矩阵能够称其为点云的外参,即形容点云的变动。至此,至多呈现了两个外参,且这两个外参所代表的物理意义齐全不一样,然而又有千头万绪的分割。咱们都晓得,宏观下静止是互相的,则必然点云的外参和对应相机的外参互逆。 注: 之所以这里对上述概念做严格辨别,次要还是因为本人之前对上述所提到的概念没有真正深刻了解,尤其是对外参的了解,导致前期算法计算呈现谬误;其二还是后续库、框架等对上述有严格辨别。 OpenMVS与纹理映射终于到了OpenMVS。。。。 已知OpenMVS能够用来浓密重建(点云)、Mesh重建(点云-->网格)、Mesh优化(非风行解决、补洞等)、网格纹理映射,正好对应源码自带的几个APP。 此处,目标只是单纯的须要OpenMVS的网格纹理映射性能!浏览国内外无关OpenMVS的应用办法,尤其国内,根本都是”一条龙“服务,总结应用流程就是 colmap/OpenMVG/visualSFM...+ OpenMVS,根本都是应用可执行文件的傻瓜式形式(网上一查一大堆),而且根本都是翻来覆去的互相”援用“(剽窃),显然不合乎本人要求与目标。吐个槽。。。 为了应用Openmvs的纹理映射模块,输出数据必须是 .mvs格式文件,额。。。.mvs是个什么鬼,我没有啊,怎么办?! 好吧,进入OpenMVS源码吧,用本人的数据去填充OpenMVS所需的数据接口。(Window10 + VS2017+OpenMVS编译省略,次要是本人过后编译的时候没做记录,不过CMake工程个别不太简单)。 场景Scene查看OpenMVS自带的几个例子,发现其必须要填充Scene类,针对本人所面对的问题,Scene类的次要构造如下: class MVS_API Scene{public: PlatformArr platforms; //相机参数和位姿 // camera platforms, each containing the mounted cameras and all known poses ImageArr images; //纹理图,和相机对应 // images, each referencing a platform's camera pose PointCloud pointcloud; //点云 // point-cloud (sparse or dense), each containing the point position and the views seeing it Mesh mesh; //网格 // mesh, represented as vertices and triangles, constructed from the input point-cloudunsigned nCalibratedImages; // number of valid imagesunsigned nMaxThreads; // maximum number of threads used to distribute the work load ... //省略代码 bool TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold=0.f, float fRatioDataSmoothness=0.3f, bool bGlobalSeamLeveling=true, bool bLocalSeamLeveling=true, unsigned nTextureSizeMultiple=0, unsigned nRectPackingHeuristic=3, Pixel8U colEmpty=Pixel8U(255,127,39)); ... //省略代码 }本人所须要的次要函数为bool TextureMesh(),可见其自带了很多参数,参数意义前期应用时再探讨。 ...

January 26, 2022 · 2 min · jiezi

关于c++:几行代码随机生成362368℃娱乐练手切记不可拿来虚报温度

#include <iostream>#include<cstdlib>#include<ctime>#define LEN 20//此处指定要生成多少个温度值int main(){ /*初始化随机数发生器*/ srand(time(NULL)); for(int i = 0; i < LEN; i++){ double x = 36.0 + (((rand()%7) + 2) / 10.0); printf("%.1f\n",x); } return 0;}仅供娱乐,事实中不要应用哦!

January 25, 2022 · 1 min · jiezi

关于c++:文本方式实现编一个函数输入一个字符串要求将所有无效字符去除空格tnr

[题目形容]编一个函数,输出一个字符串,要求做一个新字符串,把其中所有的一个或多个间断的空白字符都压缩为一个空格。这里所说的空白包含空格、'\t'、'\n'、'\r'。例如原来的字符串是:This Content hohook?file systemuttered wordsok okend.is ok?压缩了空白之后就是:This Content hoho is ok ok? file system uttered words ok ok ? end.实现该性能的函数接口要求合乎下述标准:char shrink_space(char dest, const char *src, size_t n); 给的字符比拟凌乱,所以咱们能够将其保留在文本(shrink_file.txt)中,而后将解决好的字符放在另一个输入文本(shrink_file_output.txt)中。上面是具体的实现过程:先看一下指标文本的内容代码共分为三个局部:1、一个函数判断以后字符是否为有效字符! bool is_space(char c){ if(c==' ' || c=='\t' || c=='\n' || c=='\r') return true; else return false;}2、解决凌乱字符串的外围函数shrink_space()! char *shrink_space(char *dest, const char *src, size_t n){ size_t i=0, j=0; while(i<n && src[i]) { if(is_space(src[i])) { dest[j++] = ' '; while(is_space(src[++i])) ; }else dest[j++] = src[i++]; } for(; i<n; ++i) dest[i] = '\0'; return dest;}3、而后是咱们的main函数(此处我用的是文本按行输入输出) ...

January 25, 2022 · 1 min · jiezi

关于c++:三种stdvector并发安全的设计思路

vector的并发读写问题家喻户晓,C++规范库中的vector不保障线程平安。当咱们在并发读写vector时,往往会面临两方面的危险: 内容读取异样:例如两个线程一个在读,一个在写,或者两个线程同时在写,都会导致单个数据外部呈现不统一的状况。vector扩容时,内存地位产生扭转导致Segmentation fault谬误。因为vector在扩容时会将内容全副拷贝到新的内存区域中,原有的内存区域被开释,此时如果有线程仍然在向旧的内存区域读或写就会出问题。举一个简略的例子: vector<int> vec;void add_vector(int range, unsigned int seed){ srand(seed); for(int i = 0 ; i < range; i++){ vec.push_back(rand()); }}int main(){ vec.reserve(100); thread t1 = thread(add_vector, 1000, 2); thread t2 = thread(add_vector, 1000, 1); t1.join(); t2.join();}两个线程都在向vec中增加元素,如果没有任何解决,很容易解体,就是因为第二个起因。而这种并发写的状况,在很多业务场景中都是很可能呈现的,例如:在举荐零碎中,为了进步运算效率每个线程都依照不同的策略生产举荐召回,这些线程产生召回后就会向同一个数组中合并。而后依据这些召回中选出最好的举荐后果。 在文章中提出了三种向vector并发增加元素的计划,目标是保障多线程并发条件下能正确向vector中。我的项目放在了safe_vector。 多线程平安的vector设计---有锁的设计对于解决并发问题中的最简略的设计就是加锁。在这里咱们应用规范库为咱们提供的mutex来对push_back临界区加锁。 template<typename T>class lock_vector{ std::mutex mlock; vector<T> mvec;public: T operator[](unsigned int idx){ return mvec[idx]; } lock_vector()=default; lock_vector(lock_vector<T>& vec){ vec.getVector(mvec); }; lock_vector(lock_vector<T>&& vec){ vec.getVector(mvec); }; void push_back(const T& value) noexcept{ mlock.lock(); mvec.push_back(value); mlock.unlock(); } void getVector(vector<T> & res){ res = mvec; }};多线程平安的vector设计---无锁设计除了应用互斥锁,还能够通过无锁的设计来实现线程同步。其中一种常见的思路就是CAS(compare-and-swap)。C++的原子变量(atomic)就提供了compare_exchange_weak和compare_exchange_strong来实现CAS机制。上面的代码是基于CAS实现的多线程平安计划。 ...

January 24, 2022 · 2 min · jiezi

关于c++:找出一组序列中第k小的元素要求时间复杂度为On

在浏览linuxc中看到一种快排的利用,求最小值,然而要求工夫复杂度放弃在O(n).实现如下,k代表要找的第k小! #include<iostream>using namespace std;#define LEN 8int order_partition(int a[], int low, int high,int k){ k = a[low]; while(low<high){ while(low <high && a[high]>= k ) high--; if(low<high) a[low++] = a[high]; while( low<high && a[low]<= k ) low++; if(low<high) a[high--] = a[low]; } a[low] = k; return low;}int order_K_statistic(int a[],int start,int end, int k){ int i; while(end>=start){ i = order_partition(a,start,end,k); if(k == i){ return a[i]; }else if(k > i && k < LEN){ return order_K_statistic(a,i+1,end,k); }else if(k < i && k >= 0){ return order_K_statistic(a,start,i-1,k); }else{ return -1; } }}int main(){ int a[LEN] = { 5, 2, 4, 7, 1, 3, 2, 6 }; int x = 0; for(int i = 0; i < LEN; i++){ x = order_K_statistic(a,0,LEN-1,i); printf("%d\n",x); } return 0;}能够剖析一下为什么工夫复杂度是(n),在最好状况下每次丢掉一半的元素,n+n/2+n/4+n/8+...=2n,均匀状况下的剖析比较复杂,但疾速排序相似,工夫复杂度和最好状况下统一。(摘自《linuxc》) ...

January 18, 2022 · 1 min · jiezi

关于c++:利用OpenCV进行ORB角点提取和匹配

首先构建CMakeLists.txt cmake_minimum_required(VERSION 3.21)project(ORB)set(CMAKE_CXX_STANDARD 14)find_package( OpenCV REQUIRED )include_directories( ${OPENCV_INCLUDE_DIRS} )add_executable(ORB main.cpp)target_link_libraries(ORB ${OpenCV_LIBS})编写cpp #include <iostream>#include <opencv2//core/core.hpp>#include <opencv2/features2d/features2d.hpp>#include <opencv2/highgui/highgui.hpp>using namespace std;首先读取图片 cv::Mat img_1 = cv::imread("../1.png");cv::Mat img_2 = cv::imread("../2.png");cv::imshow("img_1", img_1);cv::imshow("img_2", img_2);cv::waitKey(0);cv::destroyAllWindows();其次进行ORB角点提取的一些初始化工作 vector<cv::KeyPoint> keypoints_1, keypoints_2;cv::Mat descripions_1, descripions_2;cv::Ptr<cv::FeatureDetector> detector = cv::ORB::create(); //检测FAST角点cv::Ptr<cv::DescriptorExtractor> extractor = cv::ORB::create(); //提取形容子cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("BruteForce-Hamming"); //匹配器,应用汉明间隔STEP1 & STEP2 检测FAST角点、计算BRIEF形容子 //STEP1 检测FAST角点detector->detect(img_1, keypoints_1); //提取img_1中的角点,存储到keypoints_1中detector->detect(img_2, keypoints_2);//STEP2 计算BRIEF形容子extractor->compute(img_1, keypoints_1, descripions_1);extractor->compute(img_2, keypoints_2, descripions_2);cv::Mat outimg_1, outimg_2;cv::drawKeypoints(img_1, keypoints_1, outimg_1, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);cv::drawKeypoints(img_2, keypoints_2, outimg_2, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);cv::imshow("ORB Keypoints_img_1", outimg_1);cv::imshow("ORB Keypoints_img_2", outimg_2);cv::waitKey(0);cv::destroyAllWindows();STEP3 & STEP4 特色点匹配、特色点筛选 ...

January 16, 2022 · 1 min · jiezi

关于c++:C编译cmake简明教程

cmake简介CMake 是一个开源、跨平台的工具系列,旨在构建、测试和打包软件。CMake 用于应用简略的平台和编译器独立配置文件来控制软件编译过程,并生成可在您抉择的编译器环境中应用的本机 makefile和工作区。 cmake 存在的意义在介绍g++/gcc原理的文章中C++编译原理,咱们用一个简略的例子解说了C++编译的原理,以及g++的应用。对于生成可执行文件这项工作,咱们须要蕴含相应的头文件,以确保咱们写的源代码文件能够顺利的被编译为二进制文件。对于在代码中应用的,定义在其余库的函数和变量,咱们须要通过链接,将其具体的二进制内容,退出到可执行文件中(动静库是运行时加载),这样可执行文件能力顺利执行。 然而对于大型项目来说,为了可读性和可维护性,源代码文件往往依据性能扩散在不同层级的不同目录下,须要的第三方库和第三方头文件也是十分多的。这种状况下,如果间接用g++命令来进行我的项目构建,无疑是十分麻烦的。兴许一些老手会说能够应用MakeFile,但其实MakeFile其实就是将g++命令对应的脚本文件。 cmake的呈现就是为了帮忙构建这种大型简单我的项目。cmake为咱们提供了简洁的接口,不便咱们设置编译参数(如优化等级,报警设置等等),增加依赖(头文件和库),编译源代码等等。 须要留神的是cmake的工作并不是构建我的项目,而是生成构建我的项目的g++命令(更确切的来说就是MakeFile)。 cmake的一个简略的例子例子的源代码在这里cmake例子。例子的目录构造如下: .├── CMakeLists.txt├── include│ └── header.h├── library├── main.cpp└── src ├── add │ └── add.cpp ├── distinct │ └── distinct.cpp └── printer.cppCMakeLists.txt的内容如下: # cmake 最低版本需要cmake_minimum_required(VERSION 3.10)# 工程名称project(leak_example)# 设置编译规范为C++11set(CMAKE_CXX_STANDARD "11")# 设置编译动态库的产出目录为我的项目根目录下的library文件夹set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/library/)# 设置编译可执行文件的产出目录为我的项目根目录下set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/)# 设置蕴含头文件门路include_directories(include/)# 编译源码生成指标# 寻找src目录下所有的cpp文件(源代码文件)file(GLOB_RECURSE SRC_LIST src/*.cpp)# 将src目录下的cpp文件编译为动态库libcommon.aadd_library(common STATIC ${SRC_LIST})# 设置链接库目录link_directories(${CMAKE_SOURCE_DIR}/library/)# 将main.cpp编译为可执行文件add_executable(main main.cpp)# 减少可执行文件须要链接的动态库。肯定要放在add_executable前面,否则cmake会对main产生困惑。add_executable相当于申明了可执行文件main的存在。target_link_libraries(main libcommon.a)构建我的项目时,顺次执行以下命令: mkdir buildcd build && cmake ..此时,就能够在build文件夹下看到MakeFile文件了,cmake也就正式实现了它的使命,接着执行make,就能够看到上面的目录构造,主文件曾经呈现了可执行文件main和生成的动态库libcommon.a: ├── CMakeLists.txt├── include│ └── header.h├── library│ └── libcommon.a├── main├── main.cpp└── src ├── add │ └── add.cpp ├── distinct │ └── distinct.cpp └── printer.cpp然而可怜的是,这个程序并不能正确执行,因为外面有一些内存泄露的问题,在下一篇文章中将会介绍如何利用一些工具来定位内存泄露问题。 ...

January 14, 2022 · 1 min · jiezi

关于c++:TensorRT-开始

TensorRT 是 NVIDIA 自家的高性能推理库,其 Getting Started 列出了各材料入口,如下: 本文基于以后的 TensorRT 8.2 版本,将一步步介绍从装置,直到减速推理本人的 ONNX 模型。 装置进 TensorRT 下载页 抉择版本下载,需注册登录。 本文抉择了 TensorRT-8.2.2.1.Linux.x86_64-gnu.cuda-11.4.cudnn8.2.tar.gz,能够留神到与 CUDA cuDNN 要匹配好版本。也能够筹备 NVIDIA Docker 拉取对应版本的 nvidia/cuda 镜像,再 ADD TensorRT 即可。 # 解压进 $HOME (免得 sudo 编译样例,为以后用户)tar -xzvf TensorRT-*.tar.gz -C $HOME/# 软链到 /usr/local/TensorRT (以固定一个门路)sudo ln -s $HOME/TensorRT-8.2.2.1 /usr/local/TensorRT之后,编译运行样例,保障 TensorRT 装置正确。 编译样例样例在 TensorRT/samples,阐明见 Sample Support Guide 或各样例目录里的 README.md。 cd /usr/local/TensorRT/samples/# 设定环境变量,可见 Makefile.configexport CUDA_INSTALL_DIR=/usr/local/cudaexport CUDNN_INSTALL_DIR=/usr/local/cudaexport ENABLE_DLA=export TRT_LIB_DIR=../libexport PROTOBUF_INSTALL_DIR=# 编译make -j`nproc`# 运行export LD_LIBRARY_PATH=/usr/local/TensorRT/lib:$LD_LIBRARY_PATHcd /usr/local/TensorRT/./bin/trtexec -h./bin/sample_mnist -d data/mnist/ --fp16运行后果参考: ...

January 12, 2022 · 10 min · jiezi

关于c++:ffmpeg源码编译环境搭建

ffmpeg是视频开发最罕用到的开源软件,ffmpeg功能强大,用处宽泛,提供简直所有你可能想到的与视频开发相干的操作,许多商业软件都以ffmpeg为根底进行开发定制。 FFmpeg: FFmpeg is a free and open-source project consisting of a vast software suite of libraries and programs for handling video, audio, and other multimedia files and streams. At its core is the FFmpeg program itself, designed for command-line-based processing of video and audio files, and widely used for format transcoding, basic editing (trimming and concatenation), video scaling, video post-production effects, and standards compliance (SMPTE, ITU) . 摘自wikipediaffmpeg性能宏大,向开发者提供了丰盛的函数库调用,罕用的函数库包含: ...

January 12, 2022 · 3 min · jiezi

关于c++:-Onlogn-复杂度之排序

疾速排序不稳固 void quick_sort(int q[], int l, int r) { if (l >= r) return; // 位移和按位逻辑运算优先级低于加减 int i = l - 1, j = r + 1, pivot = q[l + r >> 1]; while (i < j) { while (q[ ++ i] < pivot); while (q[ -- j] > pivot); if (i < j) swap(q[i], q[j]); } quick_sort(q, l, j), quick_sort(q, j + 1, r);}归并排序稳固 void merge_sort(int q[], int l, int r) { if (l >= r) return; int mid = l + r >> 1; merge_sort(q, l, mid), merge_sort(q, mid + 1, r); int i = l, j = mid + 1, k = 0; while (i <= mid && j <= r) if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ]; else tmp[k ++ ] = q[j ++ ]; while (i <= mid) tmp[k ++ ] = q[i ++ ]; while (j <= r) tmp[k ++ ] = q[j ++ ]; for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];}希尔排序不稳固 ...

January 12, 2022 · 2 min · jiezi

关于c++:二分

整数二分算法bool check(int x) {/* ... */} // 查看x是否满足某种性质// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时应用:int bsearch_1(int l, int r) { while (l < r) { int mid = l + r >> 1; if (check(mid)) r = mid; else l = mid + 1; } return l;}// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时应用:int bsearch_2(int l, int r) { while (l < r) { int mid = l + r + 1 >> 1; if (check(mid)) l = mid; else r = mid - 1; } return l;}浮点数二分算法bool check(double x) {/* ... */} // 查看x是否满足某种性质double bsearch_3(double l, double r) { const double eps = 1e-6; // eps示意精度,取决于题目对精度的要求 while (r - l > eps) { double mid = (l + r) / 2; if (check(mid)) r = mid; else l = mid; } return l;}

January 11, 2022 · 1 min · jiezi

关于c++:位运算

位运算// 求n的第k位数字n >> k & 1 // 返回n的最低一位1示意的数字n & -n

January 11, 2022 · 1 min · jiezi

关于c++:leveldb-memdb源码分析上

前言最近在钻研学习leveldb的源码,并且尝试用Rust进行重写leveldb-rs,leveldb中memdb模块是应用skiplist作为一个kv的内存存储,相干代码实现十分丑陋,所以有了这篇文章。 leveldb通过应用Arena模式来实现skiplist。简略来说,就是利用线性数组来模仿节点之间的关系,能够无效防止循环援用。 c++版本的leveldb尽管也是应用的arena模式,然而节点数据内存的申请和拜访进行了封装,skiplist的构造定义和实现跟传统意义上的skiplist的代码实现十分类似,如果如果大家之前理解过skiplist的话,c++版本的代码是非常容易看懂的。golang版本leveldb 不足arena的封装,间接操作slice,如果对arena模式不相熟的话,了解起来就比拟麻烦。从软件工程角度上开,golang版本的memdb的代码写的不太好,能够进一步优化的和重构arena的操作。在本文中将会解说上面内容: 比照c++和golang版本中查问、插入、删除的实现剖析golang版本中能够优化的中央而后在下一篇文章中将会介绍 基于golang版本应用rust重写memdb(arena版本)应用rust重写一个非arena版本的memdb,也就是经典的链表构造实现形式类型申明首先咱们来比照C++和Golang的代码中的skiplist定义: C++https://github.com/google/lev... 这里次要列出要害的成员变量,具体的能够去看源码: template <typename Key, class Comparator>class SkipList {... // Immutable after construction Comparator const compare_; Arena* const arena_; // Arena used for allocations of nodes Node* const head_; // Modified only by Insert(). Read racily by readers, but stale // values are ok. std::atomic<int> max_height_; // Height of the entire list // Read/written only by Insert(). Random rnd_;};Comparator const compare_; 用来在遍历skiplist进行节点key的比拟Arena* const arena_; 应用Arena模式的内存治理Node* const head_; 首节点std::atomic max_height_; skiplist的层高,在插入的时候可能会变动Random rnd_; 随机数生成器,用于在每次插入的时候生成新节点的层高Golanghttps://github.com/syndtr/gol... ...

January 7, 2022 · 7 min · jiezi

关于c++:Eigen初见

Eigen是基于C++模板的矩阵运算库,在SLAM中是必须把握的。Eigen有一个特地的中央就是它是一个齐全用头文件搭建的库,不须要链接库文件Eigen中矩阵的定义 在CMakeLists.txt中指定Eigen的头文件目录 include_directories("usr/include/eigen3")//Eigen外围局部#include <Eigen/Core>//用于浓密矩阵的代数运算#include <Eigen/Dense>Matrix<double, 3, 3> A; Matrix<double, 3, Dynamic> B; Matrix<double, Dynamic, Dynamic> C; // 反对动静大小的矩阵Matrix3f P, Q, R; // 3x3 float matrix.Vector3f x, y, z; // 3x1 float matrix.RowVector3f a, b, c; // 1x3 float matrix.VectorXd v; // Dynamic column vector of doubles矩阵类型转换。Eigen矩阵不反对主动类型晋升,必须显式地对矩阵类型进行转换。 //// Type conversion// Eigen // MatlabA.cast<double>(); // double(A)A.cast<float>(); // single(A)A.cast<int>(); // int32(A)A.real(); // real(A)A.imag(); // imag(A)// if the original type equals destination type, no work is doneEigen 求解线性方程组 Ax = b,个别不会间接求逆,而是采纳矩阵合成,速度会快很多 ...

January 7, 2022 · 1 min · jiezi

关于c++:树与图

树的存储树的父亲表示法// datastring nodes[N];int fa[N];fa[0] = -1;void add(int b, int a) { fa[b] = a;}二叉树的儿子表示法struct Node { string data; int lc; // 未应用指针 int rc; // 未应用指针 Node() { lc = rc = -1; }};Node nodes[N];二叉树的数组表示法// datastring nodes[N];// ch[i][0]示意左儿子,ch[i][1]示意右儿子int ch[N][2];树与图的存储树是一种非凡的图,与图的存储形式雷同。无向图也是一种非凡的有向图。对于无向图中的边 xy ,存储两条有向边 x->y , y->x 。因而咱们能够只思考有向图的存储。 邻接矩阵(浓密图)bool g[N][N];void add(int x, int y) { g[x][y] = 1; }邻接表(稠密图)#include <vector>std::vector<int> g[N];// 增加一条边x->yvoid add(int x, int y) { g[x].push_back(y); }树与图的遍历深度优先遍历(邻接表)void dfs(int i) { st[i] = true; // 点i曾经被遍历过 for (auto j : g[i]) if (!st[j]) dfs(j);}宽度优先遍历(邻接表)void bfs(int i) { queue<int> q; q.push(i); st[i] = true; // 点i曾经被遍历过 while (!q.empty()) { int t = q.front(); q.pop(); for (auto j : g[t]) if (!st[j]) { q.push(j); st[j] = true; // 点j曾经被遍历过 } }}

January 6, 2022 · 1 min · jiezi

关于c++:C运算符优先级

C++的各运算符按优先级由高到低排列如下:

January 6, 2022 · 1 min · jiezi

关于c++:C数据类型

常见数据类型 浮点数binary32IEEE 754 single-precision binary floating-point format: binary64IEEE 754 double-precision binary floating-point format:

January 6, 2022 · 1 min · jiezi

关于c++:CC气象数据中心实战手把手教你做工业级项目

C/C++气象数据中心实战,手把手教你做工业级我的项目为什么要对SpringBoot返回对立的标准格局在默认情况下,SpringBoot的返回格局常见的有三种: 第一种:返回 String @GetMapping("/hello")public String getStr(){ return "hello,javadaily";}复制代码此时调用接口获取到的返回值是这样: hello,javadaily复制代码第二种:返回自定义对象download@GetMapping("/aniaml")public Aniaml getAniaml(){ Aniaml aniaml = new Aniaml(1,"pig"); return aniaml;}复制代码此时调用接口获取到的返回值是这样: { "id": 1, "name": "pig"}复制代码第三种:接口异样 @GetMapping("/error")public int error(){ int i = 9/0;return i;}复制代码此时调用接口获取到的返回值是这样: {download "timestamp": "2021-07-08T08:05:15.423+00:00", "status": 500, "error": "Internal Server Error", "path": "/wrong"}复制代码基于以上种种情况,如果你和前端开发人员联调接口她们就会很懵逼,因为咱们没有给他一个对立的格局,前端人员不知道如何处理返回值。 还有甚者,有的同学比如小张喜爱对后果进行封装,他使用了Result对象,小王也喜爱对后果进行包装,然而他却使用的是Response对象,当出现这种情况时我相信前端人员肯定会抓狂的。 所以咱们我的项目中是需要定义一个对立的标准返回格局的。 定义返回标准格局一个标准的返回格局至多蕴含3部分: status 状态值:由后端对立定义各种返回后果的状态码message 描述:本次接口调用的后果描述data 数据:本次返回的数据。{ "status":"100", "message":"操作胜利", "data":"hello,javadaily"}复制代码当然也可能按需加入其余扩大值,比如咱们就在返回对象中增加了接口调用工夫 timestamp: 接口调用工夫定义返回对象@Datadownloadpublic class ResultData<T> { /* 后果状态 ,具体状态码参见ResultData.java/ private int status; private String message; private T data; private long timestamp ; public ResultData (){ ...

January 5, 2022 · 1 min · jiezi

关于c++:静态成员实现单例模式

单例模式是一种罕用的软件设计模式。在它的外围构造中只蕴含一个被称为单例的非凡类。通过单例模式能够保证系统中一个类只有一个实例而且该实例易于外界拜访,从而不便对实例个数的管制并节约系统资源。如果心愿在零碎中某个类的对象只能存在一个,单例模式是最好的解决方案。Singleton(单例):在单例类的外部实现只生成一个实例,同时它提供一个动态getInstance()工厂办法,让客户能够拜访它的惟一实例;为了避免在内部对其实例化,将其默认构造函数和拷贝构造函数设计为公有;在单例类外部定义了一个Singleton类型的动态对象,作为内部共享的惟一实例。 用单例模式,模仿公司员工应用打印机场景,打印机能够打印员工要输入的内容,并且能够累积打印机应用次数。 class Printer{public: static Printer* getInstance(){ return pPrinter;} void PrintText(string text){ cout << "打印内容:" << text << endl; cout << "已打印次数:" << mTimes << endl; cout << "--------------" << endl; mTimes++; }private: Printer(){ mTimes = 0; } Printer(const Printer&){}private: static Printer* pPrinter; int mTimes;};Printer* Printer::pPrinter = new Printer;void test(){ Printer* printer = Printer::getInstance(); printer->PrintText("到职报告!"); printer->PrintText("入职合同!"); printer->PrintText("提交代码!");}

December 30, 2021 · 1 min · jiezi

关于c++:数据类型在超出范围赋值情况下的计算方式

背景最近在学习c++,看书看到数据类型时,运行以下代码时打印后果: #include <iostream>#include <iomanip>using namespace std;int main(){ short int i; short unsigned int j; j = 40000; i = j; cout << i << " " << j; return 0;}打印:-25536 40000因而,具体讨论一下对数据类型进行超过范畴赋值时,程序的计算过程 探讨一、首先明确,正数在计算机中是应用补码示意的拿一个字节的char类型举例,-1,原码是1000 0001,其中第8位是符号位反码是1111 1110,补码=反码+1:11111111;用无符号整型示意的话,补码的值为2^8 + (-1)所以当2^8 + (-1) = 255赋值给有符号单字节数据类型a(-128~127)时,a的值为-1 -4原码是1000 0100,反码:1111 1011,补码:1111 1100;用无符号整型示意的话,补码的值为2^8 + (-4) -128没有原码,但在计算机中用补码示意为1000 0000,用无符号整型示意的话,补码的值为2^8 + (-128)。因为2^8的二进制为1 0000 0000,128的二进制为1000 0000,所以2^8 + (-128) = 1 0000 0000 - 1000 0000 = 1000 0000 二、回到以后的场景短整型在c++中占两个字节,short int的范畴为 -32768~32767,unsigned short int的范畴为0~65535.显然,将40000赋值给short int超过了存储范畴,则i的补码的值为40000,假如i的值是-a(a是负数),2^16+(-a)=40000,-a=-25536所以i打印进去的值就是-25536 ...

December 23, 2021 · 1 min · jiezi

关于c++:算法游戏内AOI视野算法十字链表

为什么要有这个算法?对于一个游戏场景内的实体来说,当战斗频繁的时候,可能存在上千实体的数据同步,例如上千实体挪动时的坐标同步,大型战斗场景时全场景实体的属性的同步等等,这样就会造成一个问题,同步数据量十分多,然而对于客户端来说,咱们能够看到的屏幕视线大小是固定的,对于视线之外的实体的所有数据咱们并不需要晓得,所以就不须要同步,这时候就须要一种算法,能够让咱们疾速定位到在我视线范畴内的实体有哪些,而后为这些玩家同步相干的音讯。 算法数据结构设计1、为了保障链表元素的查找速度,链表应用跳表实现。2、须要xlist,ylist两条链表,须要将玩家的x,y坐标别离有序的存储到这两个链表上。 实现细节注:目前的设计仅仅基于二维 public AoiZone(float xLinksLimit, float yLinksLimit){ _xLinks = new AoiLinkedList(limit: xLinksLimit);//x轴链表 _yLinks = new AoiLinkedList(limit: yLinksLimit);//y轴链表}public AoiLinkedList(int maxLayer = 8, float limit = 0){ _limit = limit;//坐标比拟时的容错值 _maxLayer = maxLayer;//跳表层数 Add(float.MinValue);}public AoiNode Add(float target, AoiEntity entity = null){ var rLayer = 1; if (_header == null) { //创立跳表 rLayer = _maxLayer; var tempHeader = _header = new AoiNode(rLayer, target, entity);//头结点 for (var layer = _maxLayer - 1; layer >= 1; --layer) { _header = _header.Down = new AoiNode(layer, target, top: _header); //top:pre指针 down:next指针 } _header = tempHeader; return null; } //随机选取某层插入节点 while (rLayer < _maxLayer && _random.Next(2) == 0) ++rLayer; //最高的一层(节点起码的一层)头结点 AoiNode cur = _header, insertNode = null, lastLayerNode = null; for (var layer = _maxLayer; layer >= 1; --layer) { while (cur.Right != null && cur.Right.Value < target) cur = cur.Right;//与要插入地位的x/y值比拟大小(可能有新插入数据,每次都得比拟) if (layer <= rLayer) // { insertNode = new AoiNode(layer, target, entity: entity, left: cur, right: cur.Right); // if (cur.Right != null) cur.Right.Left = insertNode; cur.Right = insertNode;//节点插入 if (lastLayerNode != null) //跳表上上层指针保护 { lastLayerNode.Down = insertNode; insertNode.Top = lastLayerNode; } lastLayerNode = insertNode; } cur = cur.Down;//下一层 } Count++;//减少节点数目 return insertNode;}游戏中的update函数实现://key:实体ID//area:视线范畴//enter:此帧玩家坐标视线内的玩家public AoiEntity Refresh(long key, Vector2, out HashSet<long> enter){ var entity = Refresh(key, area); enter = entity?.ViewEntity; return entity;}public AoiEntity Refresh(long key, float x, float y, Vector2 area){ if (!_entityList.TryGetValue(key, out var entity)) return null; var isFind = false; if (Math.Abs(entity.X.Value - x) > 0) { isFind = true; _xLinks.Move(entity.X, ref x); } if (Math.Abs(entity.Y.Value - y) > 0) { isFind = true; _yLinks.Move(entity.Y, ref y); } if (isFind) Find(entity, ref area); return entity;}//此函数次要是玩家每帧挪动后,x,y坐标变换后将链表从新变成有序的过程public void Move(AoiNode node, ref float target){ var cur = node; #region Left if (target > cur.Value) //挪动后的值大于以后节点的值 { while (cur != null) { if (cur.Right != null && target > cur.Right.Value) { var findNode = cur; // Find the target node to be moved to. //此处如果节点很多,遍历可能会耗费一些性能 while (findNode.Right != null && findNode.Right.Value < target) findNode = findNode.Right; // Fuse the current node. CircuitBreaker(cur);//从以后地位移除 // Move to the target node location cur.Left = findNode; cur.Right = findNode.Right;//退出到新的地位 if (findNode.Right != null) findNode.Right.Left = cur; findNode.Right = cur; } cur.Value = target; cur = cur.Top;//调整跳表下面层的节点程序 } return; } #endregion Left #region Right while (cur != null)////挪动后的值小于以后节点的值 { if (cur.Left != null && target < cur.Left.Value) { // Find the target node to be moved to. var findNode = cur; while (findNode.Left != null && findNode.Left.Value > target) findNode = findNode.Left; // Fuse the current node. CircuitBreaker(cur); // Move to the target node location cur.Right = findNode; cur.Left = findNode.Left; if (findNode.Left != null) findNode.Left.Right = cur; findNode.Left = cur; } cur.Value = target; cur = cur.Top; } #endregion Right}private void Find(AoiEntity node, ref Vector2 area){ //将上帧的可视实体存到备份HashSet汇合里 SwapViewEntity(ref node.ViewEntity, ref node.ViewEntityBak); #region xLinks //定位到此实体,而后再xlist,ylist上别离进行left、right指针遍历,将distance在指定范畴内的实体存入此帧ViewEntity for (var i = 0; i < 2; i++) { var cur = i == 0 ? node.X.Right : node.X.Left; while (cur != null) { if (Math.Abs(Math.Abs(cur.Value) - Math.Abs(node.X.Value)) > area.X) //cur.value为aoi网格节点的value { break; } if (Math.Abs(Math.Abs(cur.Entity.Y.Value) - Math.Abs(node.Y.Value)) <= area.Y) //cur.Entity.Y.Value为以后网格节点上的实体value { if (Distance( new Vector2(node.X.Value, node.Y.Value), new Vector2(cur.Entity.X.Value, cur.Entity.Y.Value)) <= area.X) { node.ViewEntity.Add(cur.Entity.Key);//在范畴内的话 } } cur = i == 0 ? cur.Right : cur.Left; //别离在左右进行遍历 } } #endregion xLinks #region yLinks for (var i = 0; i < 2; i++) { var cur = i == 0 ? node.Y.Right : node.Y.Left; while (cur != null) { if (Math.Abs(Math.Abs(cur.Value) - Math.Abs(node.Y.Value)) > area.Y) { break; } if (Math.Abs(Math.Abs(cur.Entity.X.Value) - Math.Abs(node.X.Value)) <= area.X) { if (Distance( new Vector2(node.X.Value, node.Y.Value), new Vector2(cur.Entity.X.Value, cur.Entity.Y.Value)) <= area.Y) { node.ViewEntity.Add(cur.Entity.Key); } } cur = i == 0 ? cur.Right : cur.Left; } } #endregion yLinks}//用于函数回调//本帧绝对上帧来到视线的人public IEnumerable<long> Leave => ViewEntityBak.Except(ViewEntity);//本帧绝对上帧进入视线的人public IEnumerable<long> NewEnter => ViewEntity.Except(ViewEntityBak);//本帧绝对上帧进入视线的人测试代码private static void Main(string[] args) { var zone = new AoiZone(.001f, .001f); var area = new Vector2(3, 3); // 增加500个玩家。 for (var i = 1; i <= 500; i++) zone.Enter(i, i, i); // 刷新key为3的信息。 zone.Refresh(3, area, out var enters); Console.WriteLine("---------------id为3玩家以后视线范畴的玩家列表--------------"); foreach (var aoiKey in enters) { var findEntity = zone[aoiKey]; Console.WriteLine($"X:{findEntity.X.Value} Y:{findEntity.Y.Value}"); } // 更新key为3的坐标为(20,20)。 var entity = zone.Refresh(3, 20, 20, new Vector2(3, 3), out enters); Console.WriteLine("---------------id为3玩家挪动后来到玩家视线范畴的玩家列表--------------"); foreach (var aoiKey in entity.Leave) { var findEntity = zone[aoiKey]; Console.WriteLine($"X:{findEntity.X.Value} Y:{findEntity.Y.Value}"); } Console.WriteLine("---------------id为3玩家挪动后新退出玩家视线范畴的玩家列表--------------"); foreach (var aoiKey in entity.NewEnter) { var findEntity = zone[aoiKey]; Console.WriteLine($"X:{findEntity.X.Value} Y:{findEntity.Y.Value}"); } // 来到以后AOI zone.Exit(50);}测试后果---------------id为3玩家以后视线范畴的玩家列表--------------X:4 Y:4X:5 Y:5X:2 Y:2X:1 Y:1---------------id为3玩家挪动后来到玩家视线范畴的玩家列表--------------X:4 Y:4X:5 Y:5X:2 Y:2X:1 Y:1---------------id为3玩家挪动后新退出玩家视线范畴的玩家列表--------------X:20 Y:20X:21 Y:21X:22 Y:22X:19 Y:19X:18 Y:18现存问题此十字链表设计目前存在一个问题:当我的项目中实体数目十分多,每帧实体挪动频繁,每帧都会去进行x,y链表坐标排序,对性能耗费还是蛮大的,还在思考单纯用链表如何解决此问题。 ...

December 22, 2021 · 4 min · jiezi

关于c++:linux-gcc-下-没有c11-时的智能指针实现-参考POCO

AtomicCounter.h 线程平安的原子援用计数 实现 //// AtomicCounter.h//// Library: Foundation// Package: Core// Module: AtomicCounter//// Definition of the AtomicCounter class.//// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.// and Contributors.//// SPDX-License-Identifier: BSL-1.0//#ifndef Foundation_AtomicCounter_INCLUDED#define Foundation_AtomicCounter_INCLUDEDnamespace Poco {class AtomicCounter/// This class implements a simple counter, which/// provides atomic operations that are safe to/// use in a multithreaded environment.////// Typical usage of AtomicCounter is for implementing/// reference counting and similar things.////// On some platforms, the implementation of AtomicCounter/// is based on atomic primitives specific to the platform/// (such as InterlockedIncrement, etc. on Windows), and/// thus very efficient. On platforms that do not support/// atomic primitives, operations are guarded by a FastMutex.////// The following platforms currently have atomic/// primitives:/// - Windows/// - Mac OS X/// - GCC 4.1+ (Intel platforms only){public: typedef int ValueType; /// The underlying integer type. AtomicCounter(); /// Creates a new AtomicCounter and initializes it to zero. explicit AtomicCounter(ValueType initialValue); /// Creates a new AtomicCounter and initializes it with /// the given value. AtomicCounter(const AtomicCounter &counter); /// Creates the counter by copying another one. ~AtomicCounter(); /// Destroys the AtomicCounter. AtomicCounter &operator=(const AtomicCounter &counter); /// Assigns the value of another AtomicCounter. AtomicCounter &operator=(ValueType value); /// Assigns a value to the counter. operator ValueType() const; /// Returns the value of the counter. ValueType value() const; /// Returns the value of the counter. ValueType operator++(); // prefix /// Increments the counter and returns the result. ValueType operator++(int); // postfix /// Increments the counter and returns the previous value. ValueType operator--(); // prefix /// Decrements the counter and returns the result. ValueType operator--(int); // postfix /// Decrements the counter and returns the previous value. bool operator!() const; /// Returns true if the counter is zero, false otherwise.private: typedef int ImplType; ImplType _counter;};AtomicCounter::AtomicCounter() : _counter(0) {}AtomicCounter::AtomicCounter(AtomicCounter::ValueType initialValue) : _counter(initialValue) {}AtomicCounter::AtomicCounter(const AtomicCounter &counter) : _counter(counter.value()) {}AtomicCounter::~AtomicCounter() {}//// GCC 4.1+ atomic builtins.//inline AtomicCounter::operator AtomicCounter::ValueType() const { return _counter;}inline AtomicCounter::ValueType AtomicCounter::value() const { return _counter;}inline AtomicCounter::ValueType AtomicCounter::operator++() // prefix{ return __sync_add_and_fetch(&_counter, 1);}inline AtomicCounter::ValueType AtomicCounter::operator++(int) // postfix{ return __sync_fetch_and_add(&_counter, 1);}inline AtomicCounter::ValueType AtomicCounter::operator--() // prefix{ return __sync_sub_and_fetch(&_counter, 1);}inline AtomicCounter::ValueType AtomicCounter::operator--(int) // postfix{ return __sync_fetch_and_sub(&_counter, 1);}inline bool AtomicCounter::operator!() const { return _counter == 0; }} // namespace Poco#endif // Foundation_AtomicCounter_INCLUDEDSharedPtr 智能指针的实现 ...

December 21, 2021 · 7 min · jiezi

关于c++:中国矿业大学2021学年算法设计与分析实验课OJ2

1.Contest2425 - 毕老师算法试验一传送门在这里题目总览: A.排列问题 // 排列问题// 输出一个可能含有反复字符的字符串,打印出该字符串中所有字符的全排列。#include<bits/stdc++.h>using namespace std;bool IsSwap(vector<char> &chars, int nBegin, int nEnd){ for(int i=nBegin; i<nEnd; i++) //记住是<nEnd { if(chars[i] == chars[nEnd]) return false; } return true;}void Perm(vector<char> &chars, int k, int m){ if(k==m) { for(const char x:chars) { cout<<x; } cout<<endl; } else { for(int i=k; i<=m; i++) { if(IsSwap(chars, k, i)) { swap(chars[k], chars[i]); Perm(chars, k+1, m); swap(chars[k], chars[i]); } } }}void Foo(vector<char> &chars){ Perm(chars, 0, chars.size()-1);}// 字符串bool IsSwap(string str, int nBegin, int nEnd){ for(int i=nBegin; i<nEnd; i++) //记住是<nEnd { if(str[i] == str[nEnd]) return false; } return true;}void Perm2(string str, int k, int m){ if(k==m) { cout<<str; cout<<endl; } else { for(int i=k; i<=m; i++) { if(IsSwap(str, k, i)) { swap(str[k], str[i]); Perm2(str, k+1, m); swap(str[k], str[i]); } } }}void Foo2(string str){ str.pop_back(); cout<<str<<endl; Perm2(str, 0, str.length()-1);}int main(){ // vector<char> chars; // int n; // cin>>n; // char ele; // for(int i=0; i<n; i++) // { // cin>>ele; // chars.push_back(ele); // } // // for(const char x:chars) cout<<x; // Foo(chars); string str; // scanf("%s", str); https://blog.csdn.net/liu16659/article/details/86772657 不倡议应用scanf输出string类型 cin>>str; Foo2(str); system("pause"); return 0;}B.疾速幂 ...

December 21, 2021 · 13 min · jiezi

关于c++:中国矿业大学2021学年算法设计与分析实验课OJ

1.Contest2411 - 毕老师算法A作业一传送门在这里题目总览: A.进制转换 #include<iostream>using namespace std;long Revert(long x){ long ans = 0; long mutiply = 1; while(x) { ans += ((x%8) * mutiply); mutiply *= 10; x /= 8; } return ans;}int main(){ int x, ans; cin>>x; ans = Revert(x); cout<<ans<<endl; return 0;}B.排列问题 // B.排列问题#include<bits/stdc++.h> //奇怪之处就在于基本上所有的代码只有用了这个头文件就不再写其余头文件了。using namespace std; vector<string> ans;void Perm(string str, int low, int high){ if(low == high) { ans.push_back(str); return; } for(int i=low; i<=high; ++i) { if(i>0 && str[i]==str[i-1]) continue; //判断反复 swap(str[i], str[low]); Perm(str, low+1, high); swap(str[i], str[low]); }}int main(){ string str; cin>>str; str.pop_back(); sort(str.begin(), str.end()); Perm(str, 0, str.size()-1); sort(ans.begin(), ans.end()); for(const auto x:ans) cout<<x<<" "; system("pause"); return 0;}C.疾速幂 ...

December 21, 2021 · 14 min · jiezi

关于c++:模板的分离编译问题

存在问题的代码:test.h: #include <iostream>using namespace std;template<class T1,class T2>void func(T1 t1,T2 t2);test.cpp: #include "test.h"using namespace std;template<class T1,class T2>void func(T1 t1,T2 t2){ cout<<t1<<t2<<endl;}main.cpp: #include "test.h"int main(){ string str("ljt"); int i=5; func(str,5);}编译后果: [root@localhost cpptest]# g++ test.cpp test.h main.cpp -o test/tmp/ccp1HXnh.o:在函数‘main’中:main.cpp:(.text+0x5d):对‘void func<std::string, int>(std::string, int)’未定义的援用collect2: 谬误:ld 返回 1阐明了在main.cpp中没有找到函数func的定义。 查看起因:对test.cpp只进行编译不进行链接: [root@localhost cpptest]# g++ -c test.cpp [root@localhost cpptest]# nm -C -n test.o U __cxa_atexit U __dso_handle U std::ios_base::Init::Init() U std::ios_base::Init::~Init()0000000000000000 t __static_initialization_and_destruction_0(int, int)0000000000000000 b std::__ioinit000000000000003d t _GLOBAL__sub_I_test.cpp会发现符号表中不存在func函数,也就是编译出的二进制文件没有为func分配内存空间。起因是:模板只有在应用的时候才进行实例化。 ...

December 21, 2021 · 2 min · jiezi

关于c++:xmake-v262-发布新增-Linux-内核驱动模块构建支持

Xmake 是一个基于 Lua 的轻量级跨平台构建工具。 它十分的轻量,没有任何依赖,因为它内置了 Lua 运行时。 它应用 xmake.lua 保护我的项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对老手十分敌对,短时间内就能疾速入门,可能让用户把更多的精力集中在理论的我的项目开发上。 咱们可能应用它像 Make/Ninja 那样能够间接编译我的项目,也能够像 CMake/Meson 那样生成工程文件,另外它还有内置的包管理系统来帮忙用户解决 C/C++ 依赖库的集成应用问题。 目前,Xmake 次要用于 C/C++ 我的项目的构建,然而同时也反对其余 native 语言的构建,能够实现跟 C/C++ 进行混合编译,同时编译速度也是十分的快,能够跟 Ninja 持平。 Xmake = Build backend + Project Generator + Package Manager我的项目源码官网文档入门课程<img src="https://tboox.org/static/img/xmake/xmake-cmake.jpeg" width="30%" /> 新版本改变这个版本次要新增两大个性: Linux 内核驱动模块的构建反对分组构建和批量运行反对,可用于实现 Run all tests 性能剩下的次要是一些零散的性能改良和 Bugs 修复,能够看下文末的更新内容明细,一些比拟大的改变,上面也会逐个阐明。 新个性介绍构建 Linux 内核驱动模块Xmake 兴许是首个提供 Linux 内核驱动开发 内置反对的第三方构建工具了。 只管网上也有介绍 CMake 如何去配置构建 linux 驱动,然而大都是通过 add_custom_command 形式自定义各种命令,而后执行 echo 去本人拼接生成 Linux 的 Makefile 文件。 也就是说,其实还是依赖 Linux 内核源码的 Makefile 来执行的构建,因而如果想本人追加一些编译配置和宏定义都会十分麻烦。 ...

December 17, 2021 · 5 min · jiezi

关于c++:CC气象数据中心实战手把手教你做工业级项目sgsdga

download:C/C++气象数据中心实战,手把手教你做工业级我的项目python字符串/元组/列表/字典互转 --coding:utf-8--1、字典dict = {'name': 'Zara', 'age': 7, 'class': 'First'} 字典转为字符串,返回:<type 'str'> {'age': 7, 'name': 'Zara', 'class': 'First'}print type(str(dict)), str(dict) 字典可能转为元组,返回:('age', 'name', 'class')print tuple(dict) 字典可能转为元组,返回:(7, 'Zara', 'First')print tuple(dict.values()) 字典转为列表,返回:['age', 'name', 'class']print list(dict) 字典转为列表print dict.values 2、元组tup=(1, 2, 3, 4, 5) 元组转为字符串,返回:(1, 2, 3, 4, 5)print tup.__str__() 元组转为列表,返回:[1, 2, 3, 4, 5]print list(tup) 元组不可能转为字典3、列表nums=[1, 3, 5, 7, 8, 13, 20]; 列表转为字符串,返回:[1, 3, 5, 7, 8, 13, 20]print str(nums) 列表转为元组,返回:(1, 3, 5, 7, 8, 13, 20)print tuple(nums) ...

December 16, 2021 · 1 min · jiezi

关于c++:C右值引用与移动语义

背景开始学习C++11和筹备秋招面试时,对右值援用和挪动语义进行的深刻学习,凑巧在面试中又被问到,深刻记录一下。 左值/右值左值:能够取地址、位于等号右边 -> 有地址的变量右值:没法取地址、位于等号左边 -> 没有地址的字面值、长期值两个例子: int a = 5;a->能够通过 & 取地址,位于等号右边,是左值。5位于等号左边,5没法通过 & 取地址,所以5是个右值。struct A { A(int a = 0) { a_ = a; } int a_;};A a = A();a ------------>能够通过&取地址,位于等号右边,是左值A()-> 长期值,没法通过&取地址,位于等号左边,是右值 左值援用/右值援用援用的实质是别名。通过援用批改变量的值,传参时传援用能够防止拷贝。 左值援用右值援用参考资料https://zhuanlan.zhihu.com/p/...

December 10, 2021 · 1 min · jiezi

关于c++:ApacheCN-CC-译文集二-20211204-更新

编写高效程序的艺术 零、序言第一局部:性能根底 一、性能和并发性介绍二、性能测量三、CPU 架构、资源和性能四、内存架构和性能五、线程、内存和并发第二局部:高级并发 六、并发和性能七、并发的数据结构八、 C++ 中的并发九、高性能 C++十、C++ 中的编译器优化十一、未定义的行为和性能十二、性能设计十三、答案Code::Blocks 和 C++ 利用开发 零、前言一、Code::Blocks 入门二、Code::Blocks 利用开发三、Code::Blocks 利用调试四、应用 Code::Blocks 的 Windows 利用开发五、编程工作六、附录 A:功能集C++ 面向对象编程揭秘 零、前言第一局部:C++ 构建块要点 一、了解根本 C 语言假如二、增加语言的必须品三、间接寻址: 指针四、间接寻址: 援用第二局部:在 C++ 中实现面向对象的概念 五、具体探索类六、实现单继承层次结构七、通过多态性应用动静绑定八、把握抽象类九、摸索多重继承十、实现关联、聚合、组合第三局部:扩大您的 C++ 编程技能 十一、解决异样十二、友元和运算符重载十三、应用模板十四、理解 STL 基础知识十五、测试类和组件第四局部:C++ 中的设计模式和习语 十六、应用观察者模式十七、利用工厂模式十八、利用适配器模式十九、应用单例模式二十、应用 pImpl 模式删除实现细节二十一、答案C++17 嵌入式编程实用指南 零、前言第一局部:基础知识——嵌入式编程和 C 的作用 一、什么是嵌入式零碎?二、作为一种嵌入式语言的 C++三、面向嵌入式 Linux 和相似零碎的开发四、资源受限的嵌入式零碎五、示例——应用 WIFI 的土壤湿度监测器第二局部:测试、监控 六、测试基于操作系统的利用七、测试资源受限平台八、示例——基于 Linux 的信息娱乐零碎九、示例——建筑物监控和管制第三局部:与其余工具和框架的集成 十、应用 Qt 开发嵌入式零碎十一、混合 SoC/FPGA 零碎的开发十二、最佳实际C++ 机器人编程实用指南 零、前言第一局部:在树莓派上开始应用 wiringPi 一、树莓派简介二、应用 wiringpi 实现闪动第二局部:树莓派机器人技术 三、对机器人编程四、构建避障机器人五、应用笔记本电脑管制机器人第三局部:人脸和物体辨认机器人 六、应用 OpenCV 拜访 RPi 摄像机七、应用 OpenCV 构建跟踪对象的机器人八、将 Haar 分类器用于人脸检测和跟踪第四局部:智能手机管制机器人 ...

December 8, 2021 · 2 min · jiezi

关于c++:ApacheCN-CC-译文集-20211201-更新

笨办法学C 中文版 前言导言:C的笛卡尔之梦练习0:筹备练习1:启用编译器练习2:用Make来代替Python练习3:格式化输入练习4:Valgrind 介绍练习5:一个C程序的构造练习6:变量类型练习7:更多变量和一些算术练习8:大小和数组练习9:数组和字符串练习10:字符串数组和循环练习11:While循环和布尔表达式练习12:If,Else If,Else练习13:Switch语句练习14:编写并应用函数练习15:指针,可怕的指针练习16:构造体和指向它们的指针练习17:堆和栈的内存调配练习18:函数指针练习19:一个简略的对象零碎练习20:Zed的弱小的调试宏练习21:高级数据类型和控制结构练习22:栈、作用域和全局练习23:意识达夫设施练习24:输入输出和文件练习25:变参函数练习26:编写第一个真正的程序练习27:创造性和防御性编程练习28:Makefile 进阶练习29:库和链接练习30:自动化测试练习31:代码调试练习32:双向链表练习33:链表算法练习34:动静数组练习35:排序和搜寻练习36:更平安的字符串练习37:哈希表练习38:哈希算法练习39:字符串算法练习40:二叉搜寻树练习41:将 Cachegrind 和 Callgrind 用于性能调优练习42:栈和队列练习43:一个简略的统计引擎练习44:环形缓冲区练习45:一个简略的TCP/IP客户端练习46:三叉搜寻树练习47:一个疾速的URL路由后记:“解构 K&R C” 已死捐献名单C++ 高级编程 零、前言一、可移植的 C++ 软件分析二、不容许鸭子——类型和推导(一)三、不容许鸭子——模板和推导(二)四、不容许透露——异样和资源五、关注点拆散——软件架构、函数和可变模板六、哲学家的晚餐——线程和并发七、流和输出/输入八、每个人都会跌倒,这是你爬起来的形式——测试和调试九、对速度的需要——性能和优化十、附录C++ 高级编程秘籍 零、前言一、库的开发入门二、将异样用于错误处理三、实现挪动语义四、将模板用于泛型编程五、并发和同步六、优化代码以进步性能七、调试和测试八、创立和实现您本人的容器九、摸索类型擦除十、对动态分配的深入研究十一、C++ 中的常见模式十二、更认真查看类型推导十三、处分——应用 C++ 20 个性C++ Qt5 GUI 编程 零、前言一、Qt 简介二、Qt 小部件和样式表三、数据库连贯四、图表五、我的项目视图和对话框六、整合网络内容七、地图查看器八、图形视图九、照相机模块十、即时消息十一、实现图形编辑器十二、云存储十三、多媒体查看器十四、Qt Quick 和 QML十五、跨平台开发十六、测试和调试C++ 专家级编程 零、前言第一局部:C++ 编程的背地 一、构建 C++ 利用简介二、C++ 低级编程三、面向对象编程的细节四、了解和设计模板五、内存治理和智能指针第二局部:设计强壮高效的利用 六、STL 中数据结构和算法的开掘七、函数式编程八、并发和多线程九、设计并发数据结构十、设计全球通用的利用十一、应用设计模式设计策略游戏十二、网络和平安十三、调试和测试十四、应用 Qt 的图形用户界面第三局部:人工智能世界中的 C++ 十五、C++ 在机器学习工作中的利用十六、实现基于对话的搜索引擎十七、答案C++ 游戏动画编程实用指南 零、前言一、创立游戏窗口二、实现向量三、实现矩阵四、实现四元数五、实现转换六、构建形象渲染器七、摸索 glTF 文件格式八、创立曲线、帧和轨迹九、实现动画剪辑十、网格蒙皮十一、优化动画流水线十二、动画之间的交融十三、实现逆运动学十四、应用对偶四元数蒙皮十五、应用实例渲染人群C++ 函数式编程实用指南 零、前言第一局部:C++ 中的函数组件 一、函数式编程导论二、了解纯函数三、深刻 lambdas四、函数组合思维五、部分利用与柯里化第二局部:函数设计 六、函数思维——从数据输出到数据输入七、通过函数操作打消反复八、应用类进步内聚性九、面向函数式编程的测试驱动开发第三局部:播种函数式编程的益处 十、性能优化十一、基于属性的测试十二、重构到纯函数和通过纯函数重构十三、不变性和架构——事件源第四局部:C++ 函数式编程的现状和将来 十四、应用范畴库的提早求值十五、STL 反对和倡议十六、规范语言反对和倡议十七、答案C++ 机器学习实用指南 零、前言第一局部:机器学习概述 一、C++ 机器学习导论二、数据处理三、掂量体现和抉择模型第二局部:机器学习算法 四、聚类五、异样检测六、降维七、分类八、举荐零碎九、集成学习第三局部:高级示例 十、用于图像分类的神经网络十一、基于循环神经网络的情感剖析第四局部:生产和部署挑战 十二、导出和导入模型十三、在挪动和云平台上部署模型通过应用 UE4 构建游戏学习 C++ ...

December 8, 2021 · 2 min · jiezi

关于c++:More-Effective-C技术篇Reference-counting引用计数

Reference counting这项技术,容许多个等值对象共享同一实值。此技术的倒退有两种动机,第一是为了简化heap object周边的簿记工作。它能够打消“记录对象拥有权”的负荷,因为当对象使用了reference counting技术,它便领有它本人。一旦不再有任何人应用它,它便会主动销毁本人。reference counting的第二个倒退动机则只是为了实现一种常识。如果许多对象有雷同的值,将那个值存储屡次是件愚昧的事。最好是让所有等值对象共享一份实值就好。以下是一个蕴含了Copy-On-Write技术的Reference counting基类,有趣味倡议去看看原书中的文章,作者一步步疏导写出这个类,写的很具体,这里因为篇幅起因就不赘述。 // RCObject.h// template class,用来产生smart pointers-to-T objects;T必须继承自RCObject template<class T>class RCPtr {public: RCPtr(T* realPtr = 0); RCPtr(const RCPtr& rhs); ~RCPtr(); RCPtr& operator=(const RCPtr& rhs); T* operator->() const; T& operator*() const;private: T *pointee; void init();};// base class,用于reference-counted objectsclass RCObject {public: void addReference(); void removeReference(); void markUnshareable(); bool isShareable() const; bool isShared() const;protected: RCObject(); RCObject(const RCObject& rhs); RCObject& operator=(const RCObject& rhs); virtual ~RCObject() = 0; private: int refCount; bool shareable;};// RCObject.cppRCObject::RCObject() : refCount(0), shareable(true) {}RCObject::RCObject(const RCObject& rhs) : refCount(0), shareable(true) {}RCObject& RCObject::operator=(const RCObject& rhs) { return *this;}RCObject::~RCObject () {}void RCObject::addReference() { ++refCount;}void RCObject::removeReference() { if (--refCount == 0) { delete this; }}void RCObject::markUnshareable() { shareable = false;}bool RCObject::isShareable() const { return shareable;}bool RCObject::isShared() const { return refCount > 1;}template<class T>void RCPtr<T>::init () { if (pointee == 0) return; if (pointee->isShareable() == false) { pointee = new T(*pointee); } pointee->addReference();}template<class T>RCPtr<T>::RCPtr(T* realPtr) : pointee(realPtr) { init();}template<class T>RCPtr<T>::RCPtr(const RCPtr& rhs) : pointee(rhs.pointee) { init();}template<class T>RCPtr<T>::~RCPtr() { if (pointee) { pointee->removeReference(); }}template<class T>RCPtr<T>& RCPtr<T>::operator=(const RCPtr& rhs){ if (pointee != rhs.pointee) { if (pointee) { pointee->removeReference(); } pointee = rhs.pointee; init(); } return *this;}template<class T>T* RCPtr<T>::operator->() const { return pointee;}template<class T>T& RCPtr<T>::operator*() const { return *pointee;}而后,定义一个简略的String类,在String中蕴含示意其实值的struct StringValue,其中StringValue继承自下面的RCObject,使其领有援用计数的能力。String代码如下所示。 ...

December 8, 2021 · 2 min · jiezi

关于c++:CC气象数据中心实战手把手教你做工业级项目adafa

download:C/C++气象数据中心实战,手把手教你做工业级我的项目构造字符串 你会常常需要打印字符串。要是有很多变量,避免上面这样: name = "Raymond" age = 22 born_in = "Oakland, CA" string = "Hello my name is " + name + "and I'm " + str(age) + " years old. I was born in " + born_in + "." print(string)额,这看起来多乱呀?你可能用个丑陋简洁的方法来代替, .format 。 这样做: name = "Raymond" age = 22 born_in = "Oakland, CA" string = "Hello my name is {0} and I'm {1} years old. I was born in {2}.".format(name, age, born_in) print(string)返回tuple元组 ...

December 8, 2021 · 2 min · jiezi

关于c++:算法笔记经典模板

BFS模板void BFS(int s){ queue<int> q; q.push(s); while(!q.empty()){ 取出队首元素front; 访问队首元素front; 将队首元素出队; 将front的下一层结点中未曾入队的结点全副入队,并设置已入队 }}DFS模板递归 priority_queue的cmp函数模板:struct fruit{ string name; int price;}struct cmp{ bool operator () (fruit f1,fruit f2){ return f1.price > f2.price; }}int main(){ priority_queue<fruit,vector<fruit>,cmp> q; return 0;}中序序列和先序序列、后序序列、层序序列配合重建二叉树的模板://记住create函数模板,不论中序和谁配合,模板如下//postL是后序序列的左端点//postR是后序序列的右端点//inL是中序序列的左端点//inR是中序序列的右端点//postOrder是后序序列//inOrder是中序序列node* create(int postL,int postR,int inL,int inR){ if(postL>postR){ return NULL; } int in = postOrder[postR]; node* root = new node; root->data = in; int k; for(k=inL;k<=inR;k++){ if(inOrder[k]==in){ break; } } int numLeft = k-inL;//这一步肯定要有 root->lChild = create(postL,postL+numLeft-1,inL,inL+numLeft-1); root->rChild = create(postL+numLeft,postR-1,inL+numLeft+1,inR); return root;}并查集寻找根节点的模板://递归写法int findFather(int n){ if(n==father[n]){ return n; } else{ //小括号和中括号要离开 return findFather(father[n]); }}并查汇合并汇合的模板:void unionS(int a,int b){ int fA = findFather(a); int fB = findFather(b); if(fA != fB){ father[fA] = fB; } return;}迪杰斯特拉算法+新增点权+求最短门路条数:void Dij(){ //以下三行是初始化工作: //终点到终点的间隔是0; //终点到终点的最短门路有1条; //终点到终点累计能够取得的最大资源=该终点自身领有的资源 d[now] = 0; shortestNum[now] =1; maxRescue[now] = cityRescue[now]; //整个for循环中没有用到i的中央,i只用来计数 for(int i=0; i<cityNum; i++) { int u = -1; int minLen = inf; //寻找以后间隔终点间隔最短的点 for(int j=0; j<cityNum; j++) { if(!vis[j] && d[j]<minLen) { u = j; minLen = d[j]; } } if(u==-1) { return; } //阐明u曾经被拜访过了 vis[u] = true; int len = save[u].size(); //通过u来更新 for(int j=0; j<len; j++) { int number = save[u][j].num; int roadLen = save[u][j].road; //首先要确定该结点没有被拜访过 if(!vis[number]) { if(d[number]> d[u]+roadLen) { d[number] = d[u]+roadLen; shortestNum[number] = shortestNum[u]; //如果最短门路变了,那么累计取得的最大资源要无条件扭转 maxRescue[number] = maxRescue[u]+cityRescue[number]; } else if(d[number]==d[u]+roadLen) { shortestNum[number] += shortestNum[u]; //如果最短门路没变,那么累计取得的最大资源要有条件扭转 if(maxRescue[u]+cityRescue[number]>maxRescue[number]){ maxRescue[number] = maxRescue[u]+cityRescue[number]; } } } } }}弗罗伊德算法模板void Floyed(){ for(int k=0; k<n; k++) { for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { if(dis[i][k]!=INF && dis[k][j]!=INF && dis[i][k]+dis[k][j]<dis[i][j]) { dis[i][j] = dis[i][k]+dis[k][j]; } } } }}普里姆算法模板//G为图,个别设置成全局变量;数组d为顶点与汇合S的最短距离Prime(G,d[]){ 初始化; for(循环n次){ u = 使d[u]最小的还未被拜访的顶点的标号; 记u已被拜访; for(从u登程能达到的所有顶点v){ if(v未被拜访 && 以u为中介点使得v与汇合S的最短距离d[v]更优){ 将G[u][v]赋值给v与汇合S的最短距离d[v]; } } }}求素数模板//给定一个数,判断它是不是素数#include <iostream>#include <stdio.h>#include <math.h>using namespace std;//外围代码bool isPrime(int n){ if(n<=1){ return false; } int a = (int)sqrt(1.0*n);//向下取整 for(int i=2; i<=a; i++){ if(n%i==0){ return false; } } return true;}int main(){ int n; scanf("%d",&n); bool is = isPrime(n); if(is){ printf("Yes"); } else{ printf("No"); } return 0;}求素数表模板(埃氏筛法)//求1到n之间的所有素数,#include <iostream>#include <stdio.h>using namespace std;const int maxn = 1000;bool is[maxn] = {false};int prime[maxn];int p=0;int n;//外围代码void findPrime(){ for(int i=2;i<=n;i++){ if(!is[i]){ prime[p] = i; p++; for(int j=i+i;j<=n;j = j+i){ is[j] = true; } } }}int main(){ scanf("%d",&n); findPrime(); for(int i=0; i<p;i++){ printf("%d\n",prime[i]); } return 0;}求解最大公约数的模板//给定两个数n和m,求n和m的最大公约数a#include <iostream>#include <stdio.h>using namespace std;//外围代码;不用关怀a和b的大小,默认a>b,就算a<b,通过一轮迭代之后,也会变成a>bint gcd(int a,int b){ if(b==0){ return a; } else{ return gcd(b,a%b); }}int main(){ int n; int m; scanf("%d%d",&n,&m); int a = gcd(n,m); printf("%d",a); return 0;}求解最小公倍数的模板//给定两个数n和m,求n和m的最小公倍数b#include <iostream>#include <stdio.h>using namespace std;//外围代码int gcd(int a,int b){ if(b==0){ return a; } else{ return gcd(b,a%b); }}int main(){ int n; int m; scanf("%d%d",&n,&m); int a = gcd(n,m); int b = (n/a)*m;//先求最大公约数,而后再求最小公倍数 printf("%d",b); return 0;}求斐波拉契数列模板(动静布局办法)一个问题能用动静布局办法求解,须要满足以下两个条件: ...

December 7, 2021 · 5 min · jiezi

关于c++:算法笔记STL以及常见问题

vectorvector<typename> name 函数性能工夫复杂度push_back(x)在vector前面增加一个元素O(1)pop_back()删除vector的尾元素O(1)size()取得vector的元素个数O(1)clear()清空vector中的所有元素O(N),N为vector元素个数insert(it,x)向vector的任意迭代器it处插入一个元素xO(N)erase(it)删除迭代器it处的元素O(N)erase(first,last)删除[first,last)内的所有元素O(N)queuequeue<typename> name 函数性能工夫复杂度push(x)将x进行入队O(1)front()取得队首元素,应用前调用empty()函数O(1)back()取得队尾元素,应用前调用empty()函数O(1)pop()令队首元素出队O(1)empty()检测queue是否为空O(1)size()返回queue内元素的个数O(1)priority_queuepriority_queue<typename> name 函数性能工夫复杂度push(x)将x入队O(logN),N为以后优先队列中的元素个数top()取得队首元素(即堆顶元素),应用前调用empty()函数O(1)pop()令队首元素(即堆顶元素)出队O(logN),N为以后优先队列中的元素个数empty()检测优先队列是否为空O(1)size()返回优先队列内元素的个数O(1)priority_queue<int> q 数字越大优先级越大 priority_queue<int ,vector<int>,less<int>> q 数字越大优先级越大 priority_queue<int,vector<int>,greater<int>> q 数字越小优先级越大 #include <iostream>#include <stdio.h>#include <queue>using namespace std;struct fruit{ string name; int price; friend bool operator < (fruit f1,fruit f2)//只能对小于号进行重载 { return f1.price>f2.price; //具体了解:如果f1.price>f2.price为true,那么就认为f1 "<" f2,所以f1应该在f2前面 //与sort函数中的cmp正好相同 }} f1,f2,f3;int main(){ priority_queue<fruit> q; f1.name = "桃子"; f1.price = 3; f2.name = "梨子"; f2.price = 4; f3.name = "苹果"; f3.price = 1; q.push(f1); q.push(f2); q.push(f3); //printf("%s %d\n",q.top().name,q.top().price); cout<<q.top().name<<" "<<q.top().price<<endl; return 0;}priority_queue的用处:解决贪婪问题;对Dijkstra算法进行优化。 ...

December 5, 2021 · 1 min · jiezi

关于c++:算法笔记深度优先搜索

“让右手始终贴着左边的墙壁走” 举荐应用递归实现DFS,应用递归的时候零碎会调用零碎栈,因而用递归来实现DFS的实质还是栈 vector罕用函数: 函数性能工夫复杂度push_back(x)在vector前面增加一个元素O(1)pop_back()删除vector的尾元素O(1)size()取得vector的元素个数O(1)clear()清空vector中的所有元素O(N),N为vector元素个数insert(it,x)向vector的任意迭代器it处插入一个元素xO(N)erase(it)删除迭代器it处的元素O(N)erase(first,last)删除[first,last)内的所有元素O(N)上面给出《算法笔记》书本中的两个经典例子 背包问题求解留神点(《算法笔记》P272页)#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;const int maxn = 30;int n=0;int V=0;int maxWeight=0;int maxValue=0;int w[maxn];int v[maxn];void DFS(int index,int sumW,int sumV){ if(index==n){ return; } DFS(index+1,sumW,sumV); if(sumW+w[index]<=maxWeight){//if条件里是<=,等于号不能漏,否则会漏解,可能要完第index号物品后,背包满了,且恰好价值最大 if(sumV+v[index]>maxValue){ maxValue = sumV+v[index]; } DFS(index+1,sumW+w[index],sumV+v[index]); }}int main(){ scanf("%d%d",&n,&maxWeight); for(int i=0; i<n; i++){ scanf("%d",&w[i]); } for(int i=0; i<n; i++){ scanf("%d",&v[i]); } DFS(0,0,0); printf("%d",maxValue); return 0;}给定N个整数(可能有正数),从中选取K个数,使得这K个数之和恰好等于一个给定的整数X,如果有多种计划,抉择它们中元素平方和最大的一个(《算法笔记》P273页)#include <iostream>#include <stdio.h>#include <vector>using namespace std;const int maxn = 10000;int n=0;int k=0;int x=0;int maxSquare=-1;int A[maxn];vector<int> st;vector<int> temp;void DFS(int index,int nowk,int sum,int sumSqu)//第二个参数nowK(以后已选整数个数)容易漏写{ //死胡同1 if(nowk == k && sum == x) { if(sumSqu>maxSquare) { maxSquare = sumSqu; st = temp; } return; } //死胡同2 if(index == n || nowk >k || sum>x) ////index==n容易写成index==n-1,第n-1个数是存在的,不能被返回 { return; } //岔路口 temp.push_back(A[index]); DFS(index+1,nowk+1,sum+A[index],sumSqu+A[index]*A[index]); temp.pop_back(); DFS(index+1,nowk,sum,sumSqu);}int main(){ scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d",&A[i]); } scanf("%d",&k); scanf("%d",&x); DFS(0,0,0,0); printf("%d\n",maxSquare); for(int i=0; i<st.size(); i++) { printf("%d ",st[i]); } return 0;}参考书目:《算法笔记》 ...

December 5, 2021 · 1 min · jiezi

关于c++:算法笔记零碎知识点

10^n为n+1位数: 1000为10^3 读入double型变量的语法: double a;scanf("%lf",&a);输入double型变量的语法: printf("%f",a);或者 printf("%.2f",a);初始化字符数组的办法: char str[100]= "123a";//正文中为谬误写法//char str[100];//str= "123a";//正文中为谬误写法//char str[100];//str[100]= "123a";

December 5, 2021 · 1 min · jiezi

关于c++:算法笔记错误链表篇

for(int i=first;i!=-1; i=link[i].next){ link[i].flag = true;}上述代码中,i只有在for循环内无效,出了for循环,就有效了

December 5, 2021 · 1 min · jiezi

关于c++:算法笔记广度优先搜索

深度优先搜寻的实质是递归,广度优先搜寻不须要递归 深度优先搜寻不要用栈实现,广度优先搜寻要用队列实现 scanf()按s格局符不能输出带空格的字符串 gets()能输出带空格的字符串 scanf()以回车符作为字符串的终止符,同时不读走回车符,回车符依然留在输出缓冲区中 gets()以回车符作为字符串的终止符,同时将回车符从输出缓冲区读走,但不作为字符串的一部分 《C语言程序设计(苏小红)》P258 当须要读入字符时,能够套用以下代码: scanf("%d%d",&n,&m);for(int i=0; i<n; i++){ getchar();//过滤掉每行前面的换行符 for(int j=0; j<m; j++){ maze[i][j] = getchar(); } maze[i][m+1] = '\0;'}getchar()的作用是从零碎隐含指定的输出设施(即终端键盘)输出一个字符,按回车键示意输出完结,也承受空格 上面举一个迷宫的例子,输出一个迷宫,输出终点起点,通过广度优先搜寻失去最短门路: #include <iostream>#include <stdio.h>#include <stdlib.h>#include <queue>using namespace std;const int maxn = 1000;char maze[maxn][maxn];bool inq[maxn][maxn];int n;int m;struct node{ int x; int y; int step;};node S;node T;node mid;int ans=0;int xChange[4] = {0,0,-1,1};int yChange[4] = {1,-1,0,0};queue<node> link;bool judge(int x,int y){ if(x<0||x>=m||y<0||y>=n) { return false; } if(maze[x][y]=='*' || inq[x][y]==true) { return false; } return true;}int BFS(){ link.push(S); inq[S.x][S.y] = true; while(!link.empty()) { node temp = link.front(); link.pop(); int nowStep = temp.step; if(temp.x == T.x && temp.y == T.y){ ans = nowStep; return nowStep; } for(int i=0; i<4; i++) { int tempX = temp.x+xChange[i]; int tempY = temp.y+yChange[i]; if(judge(tempX,tempY)){ node fresh; fresh.x = tempX; fresh.y = tempY; fresh.step = nowStep+1; link.push(fresh); inq[tempX][tempY] = true; } } }//队列齐全可能为空 return -1;}int main(){ scanf("%d%d",&n,&m); for(int i=0; i<n; i++) { getchar(); for(int j=0; j<m; j++) { maze[i][j] = getchar(); } maze[i][m+1] = '\0'; } scanf("%d%d%d%d",&S.x,&S.y,&T.x,&T.y); printf("%d", BFS()); return 0;} ...

December 5, 2021 · 1 min · jiezi

关于c++:算法笔记第9章第10章各种定义总结

二叉树(Binary Tree): 要么二叉树没有根节点,是一棵空树。要么二叉树由根节点、左子树、右子树组成,且左子树和右子树都是二叉树。满二叉树: 每一层的节点数都达到了当层能达到的最大结点数。 齐全二叉树: 定义:除了最上面一层外,其余层的结点个数都达到了当层能达到的最大结点数,且最上面一层只从左至右间断存在若干结点,而这些间断结点左边的结点全副不存在。 小技巧: 1. 判断某个结点是否为叶结点的标记为:该结点(记下标为root)的左子结点的编号root*2大于结点总个数n。 2. 判断某个结点是否为空结点的标记为:该结点下标root大于结点总个数n。 二叉查找树(Binary Search Tree): 要么二叉查找树是一棵空树。要么二叉查找树由根节点、左子树、右子树组成,其中左子树和右子树都是二叉查找树,且左子树上所有结点的数据域均小于或等于根结点的数据域,右子树上所有结点的数据域均大于根节点的数据域。均衡二叉树(AVL树): AVL树依然是一棵二叉查找树(Binary Search Tree),对于AVL树的任意结点来说,其左子树和右子树的高度之差的绝对值不超过1。 其中左子树和右子树的高度之差称为该结点的均衡因子。 并查集: 并查集是一种保护汇合的数据结构,并查集反对上面两个操作: 合并:合并两个汇合。查找:判断两个元素是否在一个汇合。堆: 堆是一棵齐全二叉树,用priority_queue实现即可,priority_queue默认是大顶堆,如果想用小顶堆,就采纳上面的代码: priority_queue<int,vector<int>,greater<int>> q 数字越小优先级越大 。 度(对树而言): 把结点的子树棵数称为结点的度(degree),而树中结点的最大的度称为树的度(也称为树的宽度)。 度(对图而言): 顶点的度是指和该顶点相连的边的条数,特地是对于有向图来说,顶点的出边条数称为该顶点的出度,顶点的入边条数称为该顶点的入度。 最小生成树: 最小生成树(Minimum Spanning Tree,MST)是在一个给定的无向图 G(V,E)中求一棵树T,使得这棵树领有图G中的所有顶点,且所有边都是来自图G中的边,并且满足整棵树的边权之和最小。 最小生成树有3个性质须要把握: 最小生成树是树,因而其边数等于顶点数减1,且树内肯定不会有环。对给定的图G(V,E),其最小生成树能够不惟一,但其边权之和肯定是惟一的。因为最小生成树是在无向图上生成的,因而其根节点能够是这棵树上的任意一个结点。如果题目中波及最小生成树自身的输入,为了让最小生成树惟一,个别都会间接给出根节点,读者只须要以给出的结点作为根节点来求解最小生成树即可。参考书目:《算法笔记》

December 5, 2021 · 1 min · jiezi

关于c++:PDFium-渲染

PDFium 是 Chromium 的 PDF 渲染引擎,许可协定为 BSD 3-Clause。不同于 Mozilla 基于 HTML5 的 PDF.js,PDFium 是基于 Foxit Software (福昕软件)的渲染代码,Google 与其单干开源出的。 此外,Qt PDF 模块也选用了 PDFium ,可见 QtWebEngine / QtPdf。 本文将介绍如何用 PDFium 实现一个简略的 PDF 阅读器,代码见:https://github.com/ikuokuo/pd... 。 编译 PDFium应用预编译库:https://github.com/bblanchon/... 不然,参考 PDFium / README 本人编译,实际步骤如下: # get depot_tools, contains: gclient, ninja, gn, ...git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.gitexport PATH="$PATH:$HOME/Codes/Star/depot_tools"# get pdfiumcd pdfium-reader/mkdir -p third_party/chromiumcd third_party/chromiumgclient config --unmanaged https://pdfium.googlesource.com/pdfium.gitgclient synccd pdfium# get deps# on linux, install additional build dependencies./build/install-build-deps.sh# gn config# args see the following `out/Release/args.gn`gn args out/Release# ninja build# pdfiumninja -C out/Release pdfium# pdfium_testninja -C out/Release pdfium_test# run sample: pdf > ppm./out/Release/pdfium_test --ppm path/to/myfile.pdf期间 out/Release/args.gn 内容如下: ...

December 3, 2021 · 3 min · jiezi

关于c++:经验分享linux-下使用-Makefile-快速构建单工程教程

 欢送关注我的公众号 [极智视界],回复001获取Google编程标准 O_o >_<  o_O O_o ~_~ o_O 大家好,我是极智视界,本教程具体介绍了在 linux 下应用 Makefile 疾速构建单工程的办法。   本文的亮点是疾速构建工程,所以不会简明扼要 Makefile 语法。 间接开始,假如有一个测试 cpp: test.cpp,而后它可能会有一些依赖,如 opencv、cuda 等等,当初给出一个 Makefile,通过简略的配置就能把你的 test 可执行程序编译进去,进行疾速的测试验证工作。 ## MakefileCXX = g++CXX_FLAGS += -std=c++14CXX_FLAGS += -Wl,-rpath-linkINCLUDES += -I../xxxx/include # 头门路INCLUDES += -I../xxx/xxx/includeLINKS += -L../xxx/lib # 库门路LINKS += -L../xxx/xxx/lib LIBS += -lcuda -lcurt -pthread # 增加一些依赖库LIBS += -lopencv_imgproc -lopencv_imgcodecs -lopencv_core -lopencv_dnn# For debug build, use the command: `make debug=1' ifeq ($(debug), 1) # debug 模式 CXX_FLAGS += -DDEBUG -g endifSRCS = test.ccEXECUTABLE = test$(EXECUTABLE): $(SRCS) # 编译指令 $(CXX) $(SRCS) $(CXX_FLAGS) $(INCLUDES) $(LINKS) $(LIBS) -o $(EXECUTABLE)clean: # make clean rm -f $(EXECUTABLE)   目录树如下,也就是把俩文件放同一目录下就行: ...

December 1, 2021 · 1 min · jiezi

关于c++:G2O与多视角点云全局配准优化

背景本人手头有一堆通过初始配准后的三维散乱点云,通过粗配后,全副点云根本对立在了同一个坐标系下,如图1和图2所示。为了获取更好的全局后果,须要对粗配后的点云进行全局配准优化。 图1 点云底面 图2 部分细节 上述点云是基于pcl进行显示,不同的色彩代表不同的点云块,从图1能够显著看出,全局点云"交融"(其实并未交融,只是全副加载显示),成果较差,从图2能够看出,针对[耳朵]局部呈现较大错位。 因为本人之前对G2O多多少少有一点理解,然而也并没有进行过多深刻的钻研。晓得G2O能够用来解决全局优化问题,正好和本人要求解的问题十分十分类似。 因而,便毅然决然的抉择应用G2O来针对本人的问题构建解决方案。 G2O的进一步理解G2O是将非线性优化和图论相结合的产物,大多时候用于解决slam后端优化问题,其本身携带的例子大多也与slam无关。g2o中所谓的图,就是一堆节点和边依照肯定的关系链接而成。其中,节点是要优化的指标,边是各个优化指标之间的关系(也称其误差项,在这里本人更喜爱称为 【关系】)。 基于CMake + VS2017 实现G2O库的装置,装置过程没有做具体记录,根本百度可能解决。 装置完g2o后,依照习惯去翻看其本身源码中所携带的example,以便寻找灵感,在example目录中一眼便看中了【gicp_demo】。 G2O--gicp_demog2o的应用办法根本就是: 申明一个优化器;抉择求解办法;结构图--顶点和边的关系;优化解决。首次看到g2o的gicp时,自认为“该gicp办法是 全局(global)的”,然而事实并非如此,事实上,其甚至不能称为是一个残缺的icp问题 (对于上述红色字体的示意,目前仅仅是集体了解,或者有谬误,也请多多留言斧正,一起交流学习) 咱们晓得,ICP求解是一个迭代计算过程,经典ICP求解的次要步骤为: 输出两片点云AB,求解对应点对(三维模型至多3个不共线的点);基于对应点对,结构A到B的变换矩阵M;将M作用于A,失去A*,并用A*代替A;迭代终止条件(迭代次数或者最小误差度量);反复步骤1--3,直到满足步骤4,终止。输入变换矩阵M。然而细看g2o的gicp_demo,其流程并不如经典ICP求解过程一样,而更像一个ICP中步骤2的求解问题。 再来深刻看看g2o中给出的gicp_demo。 拆解gicp_demo首先还是间接先把g2o官网例子贴出来吧(尽管十分厌恶间接贴他人代码),便于阐明。 在该Demo中,g2o首先申明并设置了优化器optimizer,并制作了蕴含1000个点的汇合true_points作为源点云。 其次,为图增加了两个节点并设置节点ID。这里的节点类型为VertexSE3( class G2O_TYPES_SLAM3D_API VertexSE3 : public BaseVertex<6, Isometry3>),也是次要的优化指标。根据节点增加到图中的程序,将第一次增加的节点视为固定视角;vc->setEstimate(cam);该代码段通知咱们,真正求解的后果是存储在Eigen::Isometry3d类型的相机位姿(实质上是一个矩阵),这里cam参数的类型是Eigen::Isometry3d;这一步其实只是申明了两个空节点,节点参数只是单位Eigen::Isometry3d。 再次,为图增加了1000条边。在此过程中,首先依据节点id获取边所须要链接的两个顶点(节点),vp0和vp1,并基于true_points "制作" 了蕴含噪声的两个三维点pt0和 pt1(这一步其实曾经默认pt0和 pt1为对应点对);而后 申明了一个Edge_V_V_GICP类型的图边构造,该边是一个g2o的二元边(class G2O_TYPES_ICP_API Edge_V_V_GICP : public BaseBinaryEdge<3, EdgeGICP, VertexSE3, VertexSE3>),该二元边别离链接vp0和vp1;g2o还提供了EdgeGICP类型作为观测值,EdgeGICP类型能够寄存对应点对。在该步骤中,肯定要十分留神节点和三维坐标点的所属--对应关系。至此,根本可能将所有信息放入g2o的图中,该步骤次要关怀的在于如何将本人的三维点对放入到g2o图中。 最初,初始化图关系并进行了N次迭代优化,每个节点的优化后果存储在optimizer.vertices()返回值类型的哈希表中,该哈希表中:键--对应节点id,值--对应节点,这里为VertexSE3类型,从VertexSE3取得的Eigen::Isometry3d类型是咱们真正关怀的后果数据。该示例应该构建了如下一张超图,其中图有两个图节点,n1为固定节点,n2为变动的节点,节点之间有1000条边,每条边链接一对对应点,针对ICP问题,对应点中的固定点挂接图节点n1,变动的点挂接图节点n2: 节点--边 void icp() { double euc_noise = 0.01; // noise in position, m //申明优化器 SparseOptimizer optimizer; //是否打印详细信息 optimizer.setVerbose(false); // variable-size block solver //设定一个求解办法 g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg( g2o::make_unique<BlockSolverX>(g2o::make_unique<LinearSolverDense<g2o::BlockSolverX::PoseMatrixType>>())); /*g2o::OptimizationAlgorithmGaussNewton *solver = new g2o::OptimizationAlgorithmGaussNewton( g2o::make_unique<BlockSolverX>(g2o::make_unique<LinearSolverDense<g2o::BlockSolverX::PoseMatrixType>>()));*/ //设定优化器应用的优化办法 optimizer.setAlgorithm(solver); //随机点坐标 vector<Vector3d> true_points; for (size_t i = 0; i < 1000; ++i) { //这里从均匀分布中采样了一组数字 true_points.push_back(Vector3d((g2o::Sampler::uniformRand(0., 1.) - 0.5) * 3, g2o::Sampler::uniformRand(0., 1.) - 0.5, g2o::Sampler::uniformRand(0., 1.) + 10)); } // set up two poses //猜想: 设定两个相机位姿 int vertex_id = 0; for (size_t i = 0; i < 2; ++i) { // set up rotation and translation for this node //平移向量 Vector3d t(0, 0, i); //四元数旋转 Quaterniond q; q.setIdentity(); //李群(非凡欧拉群,蕴含旋转和平移,本人感觉和4*4矩阵相似) Eigen::Isometry3d cam; // camera pose cam = q; //返回平移向量的可写表达式 cam.translation() = t; // set up node //李群。这里作为节点,作为优化变量 VertexSE3 *vc = new VertexSE3(); //设置顶点的估计值 vc->setEstimate(cam); //设置该节点在 图 中的id,以便追踪 vc->setId(vertex_id); // vertex id //打印节点的初始平移和旋转矩阵 cerr << t.transpose() << " | " << q.coeffs().transpose() << endl; // set first cam pose fixed if (i == 0) vc->setFixed(true); // add to optimizer //优化器增加节点 optimizer.addVertex(vc); vertex_id++; } // set up point matches for (size_t i = 0; i < true_points.size(); ++i) { // get two poses //获取前述增加的节点。 /* optimizer.vertices()的返回值是一个哈希表(Map)类型,实质是std::unordered_map<int, Vertex*>, */ VertexSE3* vp0 = dynamic_cast<VertexSE3*>(optimizer.vertices().find(0)->second); VertexSE3* vp1 = dynamic_cast<VertexSE3*>(optimizer.vertices().find(1)->second); // calculate the relative 3D position of the point Vector3d pt0, pt1; pt0 = vp0->estimate().inverse() * true_points[i]; pt1 = vp1->estimate().inverse() * true_points[i]; // add in noise //增加高斯噪声 pt0 += Vector3d(g2o::Sampler::gaussRand(0., euc_noise), g2o::Sampler::gaussRand(0., euc_noise), g2o::Sampler::gaussRand(0., euc_noise)); pt1 += Vector3d(g2o::Sampler::gaussRand(0., euc_noise), g2o::Sampler::gaussRand(0., euc_noise), g2o::Sampler::gaussRand(0., euc_noise)); // form edge, with normals in varioius positions Vector3d nm0, nm1; nm0 << 0, i, 1; nm1 << 0, i, 1; nm0.normalize(); nm1.normalize(); //g20的二元边 Edge_V_V_GICP * e // new edge with correct cohort for caching = new Edge_V_V_GICP(); e->setVertex(0, vp0); // first viewpoint e->setVertex(1, vp1); // second viewpoint EdgeGICP meas; meas.pos0 = pt0; meas.pos1 = pt1; meas.normal0 = nm0; meas.normal1 = nm1; //定义观测值 e->setMeasurement(meas); // e->inverseMeasurement().pos() = -kp; meas = e->measurement(); // use this for point-plane //束缚信息(协方差矩阵的逆) = 点面的精度矩阵信息 e->information() = meas.prec0(0.01); optimizer.addEdge(e); } // move second cam off of its true position //变换第二个点云。 VertexSE3* vc = dynamic_cast<VertexSE3*>(optimizer.vertices().find(1)->second); Eigen::Isometry3d cam = vc->estimate(); cam.translation() = Vector3d(0, 0, 0.2); vc->setEstimate(cam); //初始化整个图构造 optimizer.initializeOptimization(); //计算所有边的误差向量 optimizer.computeActiveErrors(); //输入优化前的误差平方 cout << "Initial chi2(before opt) = " << FIXED(optimizer.chi2()) << endl; optimizer.setVerbose(true); optimizer.optimize(5); //输入优化前的误差平方 cout << "Initial chi2(after opt) = " << FIXED(optimizer.chi2()) << endl; //打印变动矩阵 cout << endl << "Second vertex should be near 0,0,1" << endl; cout << dynamic_cast<VertexSE3*>(optimizer.vertices().find(0)->second) ->estimate().translation().transpose() << endl; cout << dynamic_cast<VertexSE3*>(optimizer.vertices().find(1)->second) ->estimate().translation().transpose() << endl;}测试执行g2o自带的上述例子,最终可能打印出变换矩阵。而后将该例子独自摘出来,换入本人的数据(对应点对),也能输入变换矩阵,而后将变换矩阵作用于点云 ,后果如图3: ...

December 1, 2021 · 5 min · jiezi

关于c++:2021-年游戏开发编程语言-Top10CJavaC-霸榜前三

作为寰球增长最快的行业之一,游戏行业在近几年的倒退堪称突飞猛进,其背地的技术撑持功不可没。 近日,analyticsinsight 就出炉了 2021 年游戏我的项目开发编程语言 Top10,其中 C++、Java、C# 霸榜前三,还有不少编程语言都属于当下备受开发者欢送的编程语言。 上面就附上本次 2021 年游戏我的项目开发上榜的编程语言 Top10 列表,一起来看看吧! C++作为一种高级编程语言及游戏我的项目中最好的编程语言之一,C++ 经常被用于构建较大控制台和 Windows 游戏。它提供了许多可扩展性,可用于小型和大型游戏我的项目,且不依赖于平台,这意味着开发者能够简略地将我的项目从一个操作系统挪动到另一个操作系统。比方 The Witcher 3, Dark Souls, Elder Scrolls V: Skyrim, Player Unknown’s Battlegrounds (PUBG), Fortnite 等,都是用 C++ 创立的游戏我的项目。 JAVAJava 是 1995 年创立的通用计算机编程最佳面向对象编程语言之一。Java 被建设为具备尽可能少的依赖性,特地是与过后甚至当初的其余编程语言相比。Java 是"顶级"编程语言之一,也是2021年游戏我的项目中最风行的编程语言之一,让游戏开发人员可能为每个平台构建游戏。比方 Mission Impossible III, Minecraft, FIFA 11 以及Ferrari GT 3: World Track 等都是用 Java 开发的游戏我的项目。 C# 在宽广开发者眼中,C# 是 Windows 和 Xbox 游戏最好的编程语言之一,在像在 Unity 这样的游戏引擎中,C# 作为其编程语言( C++ 是引擎的外围)。比方 Pokemon Go 和 Super Mario Run ,都是用 C# 开发的风行游戏我的项目。 ...

November 29, 2021 · 1 min · jiezi

关于c++:C一个项目里包含多个main函数的解决

在一个我的项目的源文件中创立多个C++文件,初学时为了不便,可能会不小心书写多个main函数(每个C++文件中都有一个main函数),这样会导致编译器报错: ![上传中...]() 如果想要在一个我的项目中蕴含多个main函数能够将C++文件改为不参加生成,具体操作如下: 1.![上传中...]() 2.从生成中排除抉择“是”,确定 ![上传中...]() 3.排除后的文件会有一个红色的小小的标识 4.再次运行就不会出错了 PS 当须要抉择的文件多时,按住Ctrl键能够实现多选

November 25, 2021 · 1 min · jiezi

关于c++:多线程服务器编程4C多线程系统编程精要

线程原语的选用不间接应用Pthreads,而是应用更为易用的wrapper,封装上面的调用 线程的创立和期待完结mutex的创立、销毁、加锁、解锁条件变量的创立、销毁、期待、告诉、播送在这些wrapper之上进一步构建线程同步组件 ThreadPoolCountDownLatchBlockingQueue (有界/无界)...多线程编程须要留神的中央C++规范库容器和std::string都不是线程平安的iostream不是线程平安的线程的标识符举荐应用gettid零碎调用,它的类型是pid_t,并且是惟一的__thread是GCC内置的线程部分存储设施,效率高,但留神初始化只能应用编译器常量每个文件描述符只由一个线程操作RAII封装文件描述符不要应用多线程+fork不要应用多线程+signal

November 24, 2021 · 1 min · jiezi

关于c++:多线程服务器编程3多线程服务器的使用场合和常用模型

本章钻研对象:分布式计算的网络应用程序,基本功能能够被简略演绎为“收到数据,算一算,收回去”单线程服务器最罕用的为“non-blocking IO + IO multiplexing”,即Reactor模式,例如 lighttpdNginxlibeventJava NIOTwisted(Python)此外还有ASIO应用的Proactor模式 Reactor构造 事件循环(Event-loop)应用epoll进入阻塞监听事件,依照事件类型调用hanlder特点 须要非阻塞编程,回调函数必须是非阻塞的,只能在epoll处阻塞 这导致容易割裂业务逻辑,不容易了解与保护实用于IO密集型 计算太多也会阻塞尽管单线程模型不须要思考同步问题,但不能很好的利用多核,而如果同时应用多个过程,则势必会波及到同步问题多线程服务器阻塞+每个申请新建一个线程阻塞+线程池非阻塞 + IO multiplexing 也即作者所称的“non-blocking IO + one loop per thread”Leader/Follower等高级模式One loop per thread益处 线程数目固定不便地在线程间调配负载IO事件产生的线程是固定的,一个连贯会被注册到某个线程的loop中,并始终由这个线程负责,同一个TCP连贯不必思考并发但多线程的loop相比单线程的loop的要求变高,即须要做到线程平安,重要的问题是“如何容许一个线程往另一个线程的loop里塞货色?” 线程池实用计算工作较多的状况,重要的基础设施是BlockingQueue实现的工作队列或生产者消费者队列把计算工作或待计算数据调配给线程池中的线程过程间通信只用TCP其余IPC办法: pipe,FIFO,音讯队列,共享内存,信号TCP的益处:跨主机,伸缩性,双向,无负作用,可记录,可重现,容易定位故障 多线程服务器的实用场合解决并发连贯的两种形式Go goroutine, python gevent等的语言提供的用户态线程,由语言的runtime自行调度 便宜,能够大量创立通常配合“看起来是阻塞的IO”,这里指对于用户态的调度器阻塞,而不是对于操作系统阻塞,否则用户态多线程无奈成立内核级线程配合Reactor模式,例如libevent,muduo,Netty 数量与CPU数目相当非阻塞IO因为C++并没有第一类的工具,所以本书只思考第二类 model剖析单过程+单线程 : 没有伸缩性单过程+多线程多过程+单线程 复制多份单线程的过程,应用多个TCP port提供服务主过程+worker过程多过程+多线程 : 汇集了2和3的毛病单线程须要fork的时候须要限度程序CPU占用率的时候单线程的Reactor的次要毛病是响应工夫慢,多线程改善这一点多线程IO吞吐(网络/磁盘)是瓶颈时,多线程不会减少吞吐,这时候单线程+单过程就够了CPU算力是瓶颈时,多线程不会减少吞吐,这时候单线程+多过程更适合也更简略比照多过程8外围,压缩100个文件多过程:每个过程压缩1个文件多线程:每个文件用8个线程并行压缩总耗时雷同,因为CPU都是满载的,然而后者能更快拿到第一个压缩完的文件,这体现了多线程的低提早但实际上,线程间算法的并行度很难达到100%,所以:同一个工作,多线程或者会比多过程吞吐量降落一点,但肯定能够带来响应工夫的晋升。多线程的益处在于 能进步响应速度,让IO和计算重叠相比过程每次切换都使CPU Cache生效,线程间切换老本小,因而实用于“工作集”比拟大的状况宰割事务,将IO线程、计算线程和第三方库(例如logging)线程离开多线程应用BlockingQueue在过程间传递数据 计算操作:一个IO线程,8个计算线程(线程池),IO线程向BlockingQueue中增加数据,计算线程收到唤醒后开始计算写操作:一个独自的logging线程,通过一个或多个BlockingQueue对外提供接口,别的线程把日志写入Queue中即可,不须要期待,这样升高了服务线程的响应工夫 留神,读操作并不能利用多线程的便利性,因为无论如何都须要等到后果之后能力持续进行线程池 当计算在每次响应申请中占比比拟高时(20%以上)适宜能简化编程;防止实时创立线程的开销;加重IO线程的累赘(IO线程进行计算的话,就不能相应IO了,会导致响应速度变差)线程池的大小须要阻抗匹配,例如8核CPU,每个计算工作线程的密集计算所占工夫比重为50%,那么16个线程就能跑满全副CPU,线程池太小,会不能高效利用硬件,太大会导致额定的线程切换和内存开销多线程不能缩小工作量,而是一种兼顾的思路让工作提前完结。

November 24, 2021 · 1 min · jiezi

关于c++:多线程服务器编程2线程同步精要

线程同步的四项准则最低限度的共享对象,缩小须要同步的场合应用高级的并发构件,如TaskQueue,Producer-Consumer Queue,CountDownLatch等非不得已应用底层同步原语时,只应用非递归的互斥器和条件变量,慎用读写锁,不要应用信号量除了应用atomic整数外,不本人编写lock-free代码,也不要应用内核级同步原语互斥器(mutex)应用准则应用RAII手法封装mutex的创立、销毁、加锁、解锁 保障了锁的失效期间等于一个作用域(Scoped Locking),在死锁产生时有助于定位保障了不手工调用lock和unlock保障了不跨过程和线程调用锁保障了不遗记解锁和反复加锁只应用非递归的mutex(即不可重入的mutex)每次结构Guard对象时,思考一路上曾经持有的锁(函数调用栈),避免因桎梏程序不同导致的死锁为什么只应用非递归的mutex同一个线程能够反复对递归的mutex加锁,但不能反复对非递归的mutex加锁在同一个县城里屡次对非递归的mutex加锁会导致死锁两者性能差异不大起因 非递归的锁能提前暴露出编程问题死锁除了线程间的死锁,单个线程也会造成死锁在保障应用Scoped Locking时,能够通过剖析调用栈失去起因条件变量应用条件变量实现的BlockingQueuemuduo::MutexLock mutex;muduo::Condition cond(mutex);std::deque<int> queue;int dequeue(){ MutexLockGuard lock(mutex); while(queue.empty()){ cond.wait(); // unlock mutex and wait (原子地) } assert(!queue.empty()); int top = queue.front(); queue.pop_front(); return top;}void enqueue(int x){ { MutexLockGuard lock(mutex); queue.push_back(x); } cond.notify(); // wakeup the wait side}每次退出都调用notify(),而不是notifyall()是为了防止惊群效应不只在0->1的时候notify(),而是每加一次告诉一次,是当存在多个消费者时,能高效地唤醒他们,不然只唤醒了一个详见 https://book.douban.com/annot...应用条件变量实现CountDownLatch(倒计时)class CountDownLatch : boost::noncopyable{ public: explicit CountDownLatch(int count); void wait(); void countDown(); private: mutable MutexLock mutex_; Condition condition_; int count_;}void CountDownLatch::wait(){ MutexLockGuard lock(mutex_); whilt(count_>0){ condition_.wait(); }}void CountDownLatch::countDown(){ MutexLockGuard lock(mutex_); --count_; if(count_ == 0){ condition_.notifyAll(); }}封装MutexLock、MutexLockGuard、Condition的实现class MutexLock : boost::noncopyable{ public: MutexLock() :holder_(0) { pthread_mutex_init(&mutex_NULL); } ~MutexLock() { assert(hoilder_ == 0); pthread_mutex_destory(&mutex); } bool isLockedByThisThread(){ return holder_ == CurrentThread::tid(); } void assertLocked(){ assert(isLockedByThisThread()); } void lock(){ pthread_mutex_lock(&mutex); holder_ = CurrentThread::tid(); } void unlock(){ holder_ = 0; pthread_mutex_unlock(); } pthread_mutex_t* getPthreadMutex(){ return &mutex; } private: pthread_mutex_t mutex_; pid_t holder_; }class MutexLockGuard : boost::noncopyable{ public: explicit MutexLockGuard(MutexLock& mutex) :mutex_(mutex) { mutex_.lock(); } ~MutexLockGuard(){ mutex_.unlock; } private: MutexLock& mutex_;}#define MutexLockGuard(x) static_assert(false,"Missing mutex guard variable name!")class Condition : boost::noncopyable{ public: explicit Condition(MutexLock& mutex) :mutex_(mutex) { pthread_cond_init(&pcond_,NULL); } ~Condition(){ pthread_cond_destory(&pcond_); } void wait(){ pthread_cond_wait(&pcond_,mutex_.getPthreadMutex()); } void notify(){ pthread_cond_signal(&pcond_); } void notifyAll(){ pthread_cond_boardcast(&pcond); } private: MutexLock& mutex_; pthread_cond_t pcond_;}小结线程同步的四项准则:尽量应用高级同步设施对于其余的工作,应用一般互斥器和条件变量,采纳RAII手法和Scooped Locking

November 23, 2021 · 1 min · jiezi

关于c++:Ubuntu2004配置PCL库

目前钻研的方向是基于车载激光雷达进行路线环境的三维高精地图的构建。这种高精地图是以车载激光雷达采集的点云为基准,以图像为辅助来进行路线环境信息的辨认的提取。其中对点云的解决非常重要,针对点云进行工作,肯定绕不开PCL库。PCL(PointCloudLibrary)是一个独立凋谢的2D/3D点云跨平台C++库。PCL蕴含多个模块,如点云获取、滤波、宰割、配准、检索、特征提取、辨认、追踪、曲面重建、可视化等,为点云解决提供了极大的便当。 之前学习PCL的时候是在win10下,win10配置PCL库非常繁琐,容易出错。此外,当初小组的工作站和我本人的集体笔记本都是Ubuntu20.04,因而在Ubuntu20.04上进行PCL库的装置和配置。 整顿了网上的攻略,装置步骤如下: 1. 装置各种依赖 sudo apt-get updatesudo apt-get install git build-essential linux-libc-devsudo apt-get install cmake cmake-guisudo apt-get install libusb-1.0-0-dev libusb-dev libudev-devsudo apt-get install mpi-default-dev openmpi-bin openmpi-commonsudo apt-get install libflann1.9 libflann-devsudo apt-get install libeigen3-devsudo apt-get install libboost-all-devsudo apt-get install libqhull* libgtest-dev sudo apt-get install freeglut3-dev pkg-config sudo apt-get install libxmu-dev libxi-dev sudo apt-get install mono-complete sudo apt-get install libopenni-dev sudo apt-get install libopenni2-dev sudo apt-get install libvtk7-deb libvtk6-devsudo apt-get install qt5-default其中依照网上攻略执行sudo apt-get install libflann1.8 libflann-dev一步时产生谬误,显示显示无奈定位包libflann1.8。查阅Ubuntu Packages后发现18.04后须要libflann1.9版本,改成sudo apt-get install libflann1.9 libflann-dev后胜利装置 ...

November 16, 2021 · 2 min · jiezi

关于c++:MatrixMatrix-Multiplication

Program Assignment #2Due day: NOV. 16, 2021Problem 1: Matrix-Matrix MultiplicationIn the first hands-on lab section, this lab introduces a famous and widely-used exampleapplication in the parallel programming field, namely the matrix-matrix multiplication.You will complete key portions of the program in the CUDA language to compute thiswidely-applicable kernel.In this lab you will learn:‧ How to allocate and free memory on GPU.‧ How to copy data from CPU to GPU.‧ How to copy data from GPU to CPU.‧ How to measure the execution times for memory access and computationrespectively.‧ How to invoke GPU kernels.Your output should look like this:Input matrix file name:Setup host side environment and launch kernel:Allocate host memory for matrices M and N.M:N:Allocate memory for the result on host side.Initialize the input matrices.Allocate device memory.Copy host memory data to device.Allocate device memory for results.Setup kernel execution parameters. ...

November 12, 2021 · 2 min · jiezi

关于c++:COMP26020-C软件管理

COMP26020 Part 1– Assignment 2:Library Management Software in C++The goal of this assignment is to implement a set of C++ classes that aim to be used in a library managementsoftware. The library holds documents of different types (novels, comics and magazines) with various attributes(title, author, etc.) and users can borrow and return documents. You are given a header file library.h with thedifferent classes definitions including inheritance relationships as well as the prototypes for all classes’ methods. Afirst task is to implement each of these methods in a single C++ source file, library.cpp. To test yourimplementation, you are given a test suite in the form of a program that instantiates the classes in question, andperforms various sanity checks. A second task is to write a Makefile to automate the build of that test program.You can download an archive with the library header file as well as the test suite sources here:https://olivierpierre.github....Class HierarchyThe library.h header defines 5 classes which are briefly presented below. Note that more detailed informationabout the methods to implement is present in the header’s source code in the form of comments.• Document is an abstract class defining attributes and methods common to all the documents that can beheld in the library. Attributes include the document’s title, year of release, and quantity held in the library.It defines various methods for printing the document’s information on the standard output, getting itsconcrete type (novel/comic/magazine), and various getters/setters including methods forborrowing/returning the document from/to the library.• Novel, Comic and Magazine represent the concrete types ofdocuments. Each inheritates from Document as depicted on thefigure on the right. They differ slightly in attributes: a novel and acomic have an author, comics and magazines have an issue number,and a magazines do not have an author. Each class also defines therelevant getters/setters.• The last class, Library, represents the library i.e. a collection of documents, held in a vector attribute.The library class defines various methods for actions such as adding, removing, searching, borrowing,returning documents, printing the library content on the standard output or dumping it in a CSV file.Test SuiteTo test your implementation you are given a basic test suite in the form of a C++ file, test-suite.cpp. It’s a C++program (i.e. it contains a main function) that includes library.h. It instantiates/manipulates objects from all theaforementioned classes, and performs many sanity checks. This program uses the Catch1test framework andrequires two additional source files to be compiled: catch.cpp and catch.h. You can compile and run the testprogram as follows:$ g++ test-suite.cpp library.cpp catch.cpp -o test-suite$ ./test-suiteObviously the compilation command will fail as long as you don’t implement all of the methods invoked in the testsuite. Once it compiles and run, the program will list the tests executed and which test succeeded/failed. It is agood idea to investigate the suite source file test-suite.cpp in order to understand what is checked for eachtest. The suite is divided into tests cases enclosed into TEST_CASE() { ... } statements. A test case will failwhen one of the REQUIRE( <condition> ) or CHECK( <condition> ) statements it contains fails, i.e. whencondition evaluates to false. To complete the assignment you do not need to understand the content of catch.hand catch.cpp, these files implement the Catch engine and are rather complicated.1 https://github.com/catchorg/C...Document class hierarchyTo avoid typing the long build command, automate dependency management, and speed up the test suite build,you should write a Makefile as presented in the course.The test suite is not fully comprehensive and, although passing all the tests it contains means that a good chunk ofthe assignment has been accomplished and that the implementation seems functional, it does not mean thateverything is perfect. When marking, an extended test suite will be used, and other good C/C++ programmingpractices mentioned in the course will be taken into account such as proper memory management, code style, etc.Documents/Library Printing and CSV Output FormatsThe print() method, when called on a novel, should print on the standard the novel’s attributed following thisformat:Novel, title: Harry Potter, author: J. K. Rowling, year: 1997, quantity: 1For a comic:Comic, title: Watchmen, author: Alan Moore, issue: 1, year: 1986, quantity: 10And for a magazine:Magazine, title: The New Yorker, issue: 1, year: 1925, quantity: 20The print() method called on a library containing these 3 documents should produce:Harry Potter, author: J. K. Rowling, year: 1997, quantity: 1Comic, title: Watchmen, author: Alan Moore, issue: 1, year: 1986, quantity: 10Magazine, title: The New Yorker, issue: 1, year: 1925, quantity: 20Finally, the dumpCSV() method called on the same library should use low level file I/O functions (open, etc.) toproduce a file with the following format:novel,Harry Potter,J. K. Rowling,,1997,1comic,Watchmen,Alan Moore,1,1986,10magazine,The New Yorker,,1,1925,20Because of the cohort’s size, the exercise will be partially marked using automated tools and for that reason it isvery important to respect these formats to the letter to avoid loosing points.Deliverables, Submission & DeadlineThere are two deliverables: the completed library.cpp file, as well as the Makefile automating the build of thetest suite. The submission is made through the CS Department’s Gitlab. You should have a fork of the repositorynamed “26020-lab2-library_<your username>”. Make sure you push to that precise repository and not anotherone, failure to do so may result in the loss of some/all points. Submit your deliverables by pushing thecorresponding files on the master branch and creating a tag named lab2-submission to indicate that thesubmission is ready to be marked.The deadline for this assignment is 11/11/2021 5pm London time.Marking SchemeThe exercise will be marked out of 10, using the following marking scheme:• The program is functional, and passes the basic test suite /5• The program passes extended tests /2• The Makefile is functional and properly written /1• The program follows the good C programming practices covered in the course regarding dynamic; memoryallocation, parameter management, code style /2 ...

November 9, 2021 · 5 min · jiezi

关于c++:c学习

include门路查找     头文件是一种文本文件,应用文本编辑器将代码编写好之后,以扩展名.h保留。头文件中个别放一些重复使用的代码,例如函数申明、变量申明、常数定义、宏的定义等等。当应用#include语句将头文件援用时,相当于将头文件中所有内容,复制到#include处。#include有两种写法模式,别离是:     #include <> : 间接到零碎指定的某些目录中去找某些头文件。     #include "" : 先到源文件所在文件夹去找,而后再到零碎指定的某些目录中去找某些头文件。 编译单元(模块)     点击编译按钮生成可执行文件时,编译器做了两步工作: 将每个.cpp(.c)和相应的.h文件编译成obj文件;将工程中所有的obj文件进行LINK,生成最终.exe文件。     那么,谬误可能在两个中央产生: 编译时的谬误,这个次要是语法错误;链接时的谬误,次要是反复定义变量等。     编译单元指在编译阶段生成的每个obj文件。     一个obj文件就是一个编译单元。     一个.cpp(.c)和它相应的.h文件独特组成了一个编译单元。     一个工程由很多编译单元组成,每个obj文件里蕴含了变量存储的绝对地址等。 申明与定义     函数或变量在申明时,并没有给它理论的物理内存空间,它有时候可保障你的程序编译通过;     函数或变量在定义时,它就在内存中有了理论的物理空间。      如果你在编译单元中援用的内部变量没有在整个工程中任何一个中央定义的话,那么即便它在编译时能够通过,在连贯时也会报错,因为程序在内存中找不到这个变量。      函数或变量能够申明屡次,但定义只能有一次。 动态全局变量(static)     留神应用static润饰变量,就不能应用extern来润饰,即static和extern不可同时呈现。     static润饰的全局变量的申明与定义同时进行,即当你在头文件中应用static申明了全局变量,同时它也被定义了。     static润饰的全局变量的作用域只能是自身的编译单元。在其余编译单元应用它时,只是简略的把其值复制给了其余编译单元,其余编译单元会另外开个内存保留它,在其余编译单元对它的批改并不影响自身在定义时的值。即在其余编译单元A应用它时,它所在的物理地址,和其余编译单元B应用它时,它所在的物理地址不一样,A和B对它所做的批改都不能传递给对方。     多个中央援用动态全局变量所在的头文件,不会呈现重定义谬误,因为在每个编译单元都对它开拓了额定的空间进行存储。 全局常量(const)     const独自应用时,其个性与static一样(每个编译单元中地址都不一样,不过因为是常量,也不能批改,所以就没有多大关系)。     const与extern一起应用时,其个性与extern一样。 参考链接:https://blog.csdn.net/candyli...

November 9, 2021 · 1 min · jiezi

关于c++:Linux多线程服务器编程笔记1

C++中实现线程平安的对象创立、回调与析构写出线程平安的类并不难,应用同步原语爱护外部状态即可STL大多类都不是线程平安的,须要在内部加锁保障多个线程同时拜访平安的对象创立惟一的要求就是不要在结构期间泄露this指针,即 - 不要在构造函数中注册任何回调- 不要把this指针传给跨线程的对象- 即便在最初一行也不能够,因为这个类可能是基类,它的构造函数最初一行不等于结构实现起因:在执行构造函数期间对象没有实现初始化,如果this指针被写了泄露给了其余对象,那么别的线程可能会拜访这个半成品 平安的对象销毁对象析构函数的竞态条件1.析构某个对象时,如何得悉是否有他人在用它?2.析构某个对象时,它是否可能正在被另一个线程析构?3.调用某个对象的成员函数时,如何保障它仍旧活着?析构函数会不会碰巧执行到一半?对象析构函数的设计难点1.mutex不是方法,因为锁只是用来爱护对象外部数据的,不能来爱护对象自身,不能解决任何问题 2.面向对象中宽泛应用的三种对象关系,都依赖于对象晓得“其余对象是否还活着”的能力 a. compositionb. aggregationc. association其中,composition在多线程中不会有什么麻烦,因为对象x的生命周期由其owner惟一管制,但后两者,对象的分割是借由指针或援用实现的,因而可能会呈现下面提到的竞态条件。 解决办法 :shared_ptr / weak_ptr即在对象间中引入一层中间层,不再应用裸指针,而是智能指针,作为一个辅助的管理者(援用计数)。 shared_ptr管制对象的生命周期,是强援用,只有有一个指向x对象的shared_ptr存在,x就不会析构,当援用计数降为0时或reset()时,x保障会被销毁。weak_ptr不管制对象生命周期,但晓得对象是否或者,如果对象没死,那么能够晋升为无效的shared_ptr,从而援用对象,并保障在这个期间对象不析构,如果对象死了,那么会返回空的shared_ptr。晋升行为是线程平安的。shared_ptr和weak_ptr的计数是原子操作,性能不俗然而 ❗ shared_ptr和weak_ptr自身的线程安全级别与std::string和STL的容器一样,见上面的探讨对于shared_ptr的探讨shared_ptr并不线程平安:能够多个线程同时读,不能多个线程同时写(析构算写)shared_ptr的线程平安和它指向对象的线程平安是两回事访问共享的shared_ptr,须要加上互斥锁 void read(){ shared_ptr<Foo> localPtr; { MutexLockGuard lock(mutex); localPtr = globalPtr; // read globalPtr } // use localPtr since here,读写localPtr无需加锁,因为是栈上对象,只有以后线程可见 do_it(localPtr); // 这里函数的参数应是reference to const,防止复制}weak_ptr和shared_ptr用错,可能会导致一些对象永远不被析构,通常做法是owner领有指向child的shared_ptr,child持有owner的weak_ptr拷贝开销:因为拷贝会创立一份正本,须要批改援用计数,开销较大,但须要拷贝的中央不多,通常shared_ptr作为参数时都是const reference。RAII 资源获取即初始化C++区别于其余编程语言的最重要的个性每一个明确的资源配置动作(如new)都应该在繁多语句中执行,并在该寄居中立即将配置取得的资源交给handle对象(如shared_ptr),程序中个别不呈现delete线程平安的对象池实现一个StcokFactory, 依据key返回Stock对象 版本1: 利用weak_ptr和shared_ptr治理 class StockFactory : boost::noncopyable{ public: boost::shared_ptr<Stock> get(const string& key) { boost::shared_ptr<Stock> pStock; muduo::MutexLockGuard lock(mutex_); boost::weak_ptr<Stock>& wkStock = stocks_[key]; // 如果这里是shared_ptr,则对象永远不会被析构 pStock = wkStock.lock(); if (!pStock) { pStock.reset(new Stock(key)); wkStock = pStock; // wkStock is a reference } return pStock; } private: mutable muduo::MutexLock mutex_; std::map<string, boost::weak_ptr<Stock> > stocks_;};问题: 存在轻微的内存透露,map中的key:weak_ptr会始终存在,在key无限时没什么问题,在key范畴很大时会造成内存透露 ...

November 8, 2021 · 2 min · jiezi

关于c++:C是如何调用C接口的

✨有的时候,当我想在c++代码中调用c接口,而后就编译报错了!!!引出问题你可能会奇怪,C++不是兼容C吗?间接调用不就能够了?为什么会有这样的状况呢?设想一下,有些接口是用C实现的,并提供了库,那么C++中该如何应用呢? 咱们先不做任何区别对待,看看一般状况下会产生什么意想不到的事件。首先提供一个C接口: //test.c#include"test.h"void testCfun(){ printf("I am c fun\n"); return;}咱们在这里编译成C指标文件: gcc -c test.c另外提供一个头文件test.h: #include<stdio.h>void testCfun();咱们的C++代码调用如下: //main.cpp#include"test.h"#include<iostream>using namespace std;int main(void){ /*调用C接口*/ cout<<"start to call c function"<<endl; testCfun(); cout<<"end to call c function"<<endl; return 0;}编译: $ g++ -o main main.cpp test.o/tmp/ccmwVJqM.o: In function `main':main.cpp:(.text+0x21): undefined reference to `testCfun()'collect2: error: ld returned 1 exit status很可怜,最初的链接报错了,说找不到testCfun,然而咱们的确定义了这个函数。为什么会找不到呢? 揭开迷雾咱们都晓得,C++中函数反对重载,而C并不反对。C++为了反对函数重载,它在“生成”函数符号信息时,不能仅仅通过函数名,因为重载函数的函数名都是一样的,所以它还要依据入参,命名空间等信息来确定惟一的函数签名。 或者说C++生成函数签名的形式与C不统一,所以即使是函数名一样,对于C和C++来说,它们最终的函数签名还是不一样。当然这里又是另外一回事了,咱们不细说。咱们看看两个文件里的函数符号有什么区别: $ nm test.o|grep testCfun0000000000000000 T testCfun$ nm main.o|grep testCfun U _Z8testCfunv所以它们两个能链接在一起才真是奇怪了呢!名字都不同,还怎么链接? 解决办法那么如何解决呢?很显然,咱们必须通知链接器,这是一个C接口,而不是C++接口,所以须要退出 extern C,咱们批改test.h #include<stdio.h>extern "C"{void testCfun();}这里用extern "C"将testCfun接口包裹起来,通知编译器,这里的是C接口哈,你要按C代码的形式解决。再次编译: ...

November 8, 2021 · 1 min · jiezi

关于c++:编程艺术谈谈和分享-Google-编程规范

 欢送关注我的公众号 [极智视界],回复001获取Google编程标准 O_o >_<  o_O O_o ~_~ o_O 本文介绍和分享一下 Google 编程标准。   刚接触编程的同学往往更加偏向于代码性能的实现,而疏忽代码编写标准,这会导致你写的代码极难保护,造成你的代码只有你能看懂的困境。特地是波及较大型我的项目,须要多人协同开发的场景,更是对代码标准的约定与对立要求严苛,这很好了解,代码标准便于我的项目的迭代、保护与对接。   对于开源我的项目也是一样,每个较大的开源我的项目都有本人的格调指南,以便于开源我的项目的推广,这个格调指南是对于如何为该我的项目编写代码的一系列约定,当所有代码均保持一致的格调, 在了解大型代码库时会变得更为轻松。格调的含意涵盖范围广, 从变量应用驼峰格局 (camelCase)到决不应用全局变量再到决不应用异样,这些都是代码编程的标准。   Google 常常会公布一些开源我的项目,意味着会承受来自其余代码贡献者的代码,然而如果代码贡献者的编程格调与 Google 的不统一,会给代码阅读者和其余代码提交者造成不小的困扰。Google 因而公布了《Google 编程标准》这份指南,使所有提交代码的人都能获知 Google 的编程格调。规定的作用就是防止凌乱,但规定自身肯定须要具备权威性、有说服力并且是感性的,正好 Google 的这份编程标准具备这些个性,目前这份编程标准成为了越来越多开发者代码编程的统一标准,Google 目前曾经公布了五份中文版的分格指南:   (1) Google C++ 格调指南;   (2) Google Objective-C 格调指南;   (3) Google Python 格调指南; (4) Google Shell 格调指南;   (5) Google Javascript 格调指南; 当然对于以上的这些在我的公众号里回复 001 你都能拿到,中文版我的项目采纳 reStructuredText 纯文本标记语法,并应用 Sphinx 生成 HTML / CHM/ PDF 等文档格局。 ...

November 1, 2021 · 1 min · jiezi

关于c++:xmake-v259-发布改进-C20-模块并支持-Nim-Keil-MDK-和-Unity-Build

xmake 是一个基于 Lua 的轻量级跨平台构建工具,应用 xmake.lua 保护我的项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对老手十分敌对,短时间内就能疾速入门,可能让用户把更多的精力集中在理论的我的项目开发上。 这个版本,咱们减少了大量重量级的新个性,例如:Nim 语言我的项目的构建反对,Keil MDK,Circle 和 Wasi 工具链反对。 另外,咱们对 C++20 Modules 进行了大改良,不仅反对最新 gcc-11, clang 和 msvc 编译器,而且还得模块间依赖做了主动剖析,实现最大水平的并行化编译反对。 最初,还有一个比拟有用的个性就是 Unity Build 反对,通过它咱们能够对 C++ 代码的编译速度做到很大水平的晋升。 我的项目源码官网文档入门课程新个性介绍Nimlang 我的项目构建最近,咱们新增了对 Nimlang 我的项目的构建反对,相干 issues 见:#1756 创立空工程咱们能够应用 xmake create 命令创立空工程。 xmake create -l nim -t console testxmake create -l nim -t static testxmake create -l nim -t shared test控制台程序add_rules("mode.debug", "mode.release")target("test") set_kind("binary") add_files("src/main.nim")$ xmake -v[ 33%]: linking.release test/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/test/macosx/x86_64/release/nimcache -o:build/macosx/x86_64/release/test src/main.nim[100%]: build ok!动态库程序add_rules("mode.debug", "mode.release")target("foo") set_kind("static") add_files("src/foo.nim")target("test") set_kind("binary") add_deps("foo") add_files("src/main.nim")$ xmake -v[ 33%]: linking.release libfoo.a/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/foo/macosx/x86_64/release/nimcache --app:staticlib --noMain --passC:-DNimMain=NimMain_B6D5BD02 --passC:-DNimMainInner=NimMainInner_B6D5BD02 --passC:-DNimMainModule=NimMainModule_B6D5BD02 --passC:-DPreMain=PreMain_B6D5BD02 --passC:-DPreMainInner=PreMainInner_B6D5BD02 -o:build/macosx/x86_64/release/libfoo.a src/foo.nim[ 66%]: linking.release test/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/test/macosx/x86_64/release/nimcache --passL:-Lbuild/macosx/x86_64/release --passL:-lfoo -o:build/macosx/x86_64/release/test src/main.nim[100%]: build ok!动静库程序add_rules("mode.debug", "mode.release")target("foo") set_kind("shared") add_files("src/foo.nim")target("test") set_kind("binary") add_deps("foo") add_files("src/main.nim")$ xmake -rv[ 33%]: linking.release libfoo.dylib/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/foo/macosx/x86_64/release/nimcache --app:lib --noMain -o:build/macosx/x86_64/release/libfoo.dylib src/foo.nim[ 66%]: linking.release test/usr/local/bin/nim c --opt:speed --nimcache:build/.gens/test/macosx/x86_64/release/nimcache --passL:-Lbuild/macosx/x86_64/release --passL:-lfoo -o:build/macosx/x86_64/release/test src/main.nim[100%]: build ok!C 代码混合编译add_rules("mode.debug", "mode.release")target("foo") set_kind("static") add_files("src/*.c")target("test") set_kind("binary") add_deps("foo") add_files("src/main.nim")Nimble 依赖包集成残缺例子见:Nimble Package Example ...

October 31, 2021 · 5 min · jiezi

关于c++:More-Effective-C技术篇要求或禁止对象产生于heap之中

要求对象产生于heap中,意思是须要阻止clients不得应用new以外的办法产生对象。比拟好的办法就是将destructor定义为private,因为constructor的类型太多,所以依然将constructor定义为public。而后定义一个pseudo destructor来调用真正的destructor。示例如下: class HeapBasedObject {public: HeapBasedObject() {} void destroy() const { delete this; } // pseudo destructorprivate: ~HeapBasedObject() {}};int main(){ //HeapBasedObject h; HeapBasedObject *ph = new HeapBasedObject; //delete ph; ph->destroy();}禁止对象产生于heap中,则是要让clients不能应用new办法来产生对象。办法就是将operator new和operator delete定义为private。示例如下: #include <stdlib.h>class NoHeapBasedObject {public: NoHeapBasedObject() {} ~NoHeapBasedObject() {}private: static void *operator new(size_t size) {} static void operator delete(void *ptr) {}};int main(){ NoHeapBasedObject nh; static NoHeapBasedObject snh; //NoHeapBasedObject *pnh = new NoHeapBasedObject;}下例是实现的一个判断某个对象是否位于heap内的基类HeapTracked。 #include <stdlib.h>#include <list>#include <iostream>class HeapTracked {public: class MissingAddress{}; //地址异样 virtual ~HeapTracked() = 0; static void *operator new(size_t size); static void operator delete(void *ptr); bool isOnHeap() const;private: typedef const void* RawAddress; static std::list<RawAddress> addresses;};std::list<HeapTracked::RawAddress> HeapTracked::addresses;HeapTracked::~HeapTracked() {}void* HeapTracked::operator new(size_t size) { void* memPtr = ::operator new(size); // 获得内存。 addresses.push_front(memPtr); // 将其地址置于list头部。 return memPtr;}void HeapTracked::operator delete(void *ptr) { auto it = std::find(addresses.begin(), addresses.end(), ptr); if (it != addresses.end()) { addresses.erase(it); ::operator delete(ptr); } else { throw MissingAddress(); }}bool HeapTracked::isOnHeap() const { auto rawAddress = dynamic_cast<const void*>(this); auto it = std::find(addresses.begin(), addresses.end(), rawAddress); return it != addresses.end();}class Object: public HeapTracked {public: Object() {} ~Object() {}};int main(){ Object o1; Object* o2 = new Object; std::cout << "o1 isOnHeap = " << o1.isOnHeap() << std::endl; std::cout << "o2 isOnHeap = " << o2->isOnHeap() << std::endl;}

October 31, 2021 · 1 min · jiezi

关于c++:open-code-reading

C/C++ Projectsglog: 10/27/2021-10/28/2021cJSON: 10/28/2021-10/29/2021luaprotobufgrpc: https://grpc.io/libstdc++follyredisnginxmemcached

October 30, 2021 · 1 min · jiezi

关于c++:COMP1521-MIPS讲解

10/26/21, 11:39 AM COMP1521 21T3 — Assignment 1: minesweeper, MIPS minesweeper 1/11Assignment 1: minesweeper, MIPS minesweeperversion: 1.6 last updated: 2021-10-18 20:00:00Aimsto give you experience writing MIPS assembly codeto give you experience with data and control structures in MIPSGetting StartedCreate a new directory for this assignment called minesweeper, change to this directory, and fetch the provided code by running thesecommands:$ mkdir minesweeper$ cd minesweeper$ 1521 fetch minesweeperIf you're not working at CSE, you can download the provided files as a zip file or a tar file.This will add the following files into the directory:grid.h: some grid related constants in C, such as its size.grid.s: the MIPS version of grid.h.beginner.[hs]: more constants in C and MIPS.intermediate.[hs]: more constants in C and MIPS.expert.[hs]: more constants in C and MIPS.minesweeper.c: a reference implementation of Minesweeper in C.minesweeper.s: a stub assembly file to complete.MinesweeperHow to play Minesweeperminesweeper.c is an implementation of the classic game Minesweeper. The objective of the game is to clear a board that contains hidden"mines" or bombs without detonating any of them. To do this, you will need to use the clues on the board, which indicate how manybombs are in the adjacent cells.At any point, you can perform 2 actions:Marking a cell - marking or flagging a cell that you think might be a bomb,Revealing a cell - revealing the cell. If it is an empty cell, then all of the surrounding empty cells will also be revealed. Revealing acell containing a bomb is game over.Once you have revealed all cells that do not contain a bomb, you win the game.Before starting the assignment, it is recommended that you understand how to play Minesweeper. A good place to start is Google'sbuilt-in minesweeper game that can be found here.minesweeper.cThe assignment version of Minesweeper is played on a grid represented by a 2D array of 8-bit ints (int8_t **grid). Each element in the2D array represents a cell on the grid. For each element in the 2D array, 7 of the 8 bits are used to represent information regarding thatcell, as shown in the diagram below.is_marked - 1 if cell is marked, 0 if not.is_revealed - 1 if cell is revealed, 0 if not.is_bomb - 1 if cell is a bomb, 0 if not.value - number of bombs in adjacent cells, including diagonally adjacent cells. This will hold the value of 0 - 8 as there are a totalof 8 adjacent cells. The value 0 represents an empty cell.10/26/21, 11:39 AM COMP1521 21T3 — Assignment 1: minesweeper, MIPS minesweeper 2/11You can use bitwise operations to extract or set relevant bits. The relevant masks are #defined at the top of the minesweeper.c file.By default, the game is played on a 10x10 grid. However, you can change these settings to play on a different sized grid by changing the ...

October 29, 2021 · 21 min · jiezi