std::make_shared和new初始化智能指针的区别

先看代码:

class Base
{
    public:
        Base(int num):a(num) {std::cout << "Base() construct" << std::endl;}
        ~Base() {std::cout << "Base() deconstruct" << std::endl;}
        int Get() {return a;}
        
    private:
        int a;
};

void testc()
{
        std::cout << "******************************" << std::endl;
        std::cout << "******************************" << std::endl;
        
        Base *p;
        {
            std::weak_ptr<Base> gw;
            {
                auto sp = std::make_shared<Base>(42);
                gw = sp;
                p = sp.get();
            }
            std::cout << "shared_ptr release, p->a = " << p->Get() << std::endl;
        }
        std::cout << "weak_ptr release, p->a = " << p->Get() << std::endl;
}

void testd()
{
        std::cout << "==================================" << std::endl;

        
        Base *p;
        {
            std::weak_ptr<Base> gw;
            {
                std::shared_ptr<Base> sp(new Base(42));
                gw = sp;
                p = sp.get();
            }
            std::cout << "shared_ptr release, p->a = " << p->Get() << std::endl;
        }
        std::cout << "weak_ptr release, p->a = " << p->Get() << std::endl;
}

执行结果如下:

在testc()中,只有weak_ptr生命周期也结束后,Base对象内存才真正被回收,虽然Base在shared_ptr生命周期结束后就执行了析构函数,但对象所占用的内存还未被马上回收。

而在testd()中,由于使用了new分配对象内存,Base对象内存和智能指针控制块内存不在一起,所以当shared_ptr生命周期结束后就释放了Base对象所占内存。

结论:

1、make_shared只分配一次内存,智能指针控制块和管理的对象存在同一块内存里。new初始化智能指针需要调用两次内存分配,一次给控制块分配内存,一次给对象分配内存。

2、异常安全性。当在函数的实参里初始化智能指针,使用new初始化有发生异常安全性的风险,如 function_a(std::shared_ptr ptr1(new int(100)), function_b()); 编译器可能产生代码: 1先new对象,2再执行函数function_b,3最后将new对象的指针赋给智能指针,如果第2步 function_b发生异常退出,将导致内存泄漏。

3、对象内存被延迟回收:当使用了弱指针weak_ptr引用shared_ptr时,使用make_shared初始化因为控制块和对象都在同一块内存里,虽然管理的对象已经执行析构函数,但由于weak_ptr没有释放,导致内存生命周期被意外延长,只有weak_ptr生命周期结束后,整块内存才一起被回收

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
In the fall of 1998 Bill Joy and Mike Clary asked us to help establish a community of developers and companies around Sun's then-new Jini network technology. Jini is a simple distributed computing model based on the Java programming language that enables services running on different computer systems to spontaneously interact with each other over the network with minimal pre- planning for such interactions. For Jini to succeed, it was clear that the underlying Jini protocols and infrastructure would need to become pervasive, and to accomplish that would require a strong community of participants and partners. Moreover Sun did not have the expertise to define Jini services in areas like printing, digital photography, storage, white goods, or the many other potential markets for products that would benefit from being network enabled. As a preliminary step the Sun Community Source License (SCSL) had been developed to provide a framework where the source code for Jini could be safely shared. SCSL is not true open source, but has many of the same characteristics. However a license and providing the source code were not enough~there had to be more to motivate people to participate. We worked with the Jini engineering and marketing teams to apply the lessons we had learned from being involved in various open source and community development projects and from our studies of complexity science to create a true Jini Community. We worked hard to help establish an identity for the community. To build identity and culture requires face-to-face interaction, so we organized community meetings that were held in interesting places and featuring non-traditional speakers. The first Jini Community meeting was at the Aspen Institute in Aspen, Colorado. We played team-building games, we engaged a recording graphic artist, we broke into groups in unusual ways. 1 We encouraged nonstandard thinking and speaking as individuals rather than as representatives of companies at times. The keynote speakers included Robert Dahl, a political scientist, talking "On Democracy," and Thomas Petzinger, a Wall Street Journal columnist, speaking about new business models based on cooperation. We also helped create a website for the project (http://www.jini.org) as a meeting place, a newspaper, a repository of shared documents, a totem, and a place to share work and projects. Most of the shared assets of the community could be accessed there. The website had a public part that advertised the community, and private parts for members only to help foster community identity. Common vocabulary leads to shared stories and then to shared beliefs. We created a pattern language on how the Jini Community could work, which has served to create a shared vocabulary--terms like dangerous waterhole, cut ~r run, and microcosm that serve as linguistic markers for the uniqueness of the community and culture. The pattern language was designed to teach how to build (self-) governance structures and procedures on the fly which have proven to be comfortable and delightful in the past but which were to be tailored to the specific on-the-spot needs of the community. We also worked with the community on developing a formal decision-making process and a "community process" for the purpose of ratifying definitions for Jini services. The former was to make it clear how community-wide decisions are made--how are proposals created, how are they voted on, how are appeals made--and the latter was to specify how the community can officially bless or endorse a service definition. The request to help build a community around a technology for business purposes led us to research and think about business in the commons. How do open-source projects work? How can a company participate? Why would a company engage in an activity centered around giving things away? How and why could such a thing work? Since the spring of 2000 we have done similar work with other Sun-sponsored open-source projects such as NetBeans, OpenOffice, Project JXTA, and java.net. We have worked with each of those teams to help them to define their open source strategy along with how to implement it. This book contains not only the lessons we have learned from helping to create and nurture communities around these Sun-sponsored and other open source and community development projects, but the fruit of years of participation in innovative communities of many sorts. Specifically, one of us 2 was the originator of the Common Lisp Group, which is the first, large-scale, email-based design effort; this group worked from 1981 until the early 1990s. The same author 2 founded Lucid, Inc, one of whose products~designed and implemented in the late 1980s~used a suite of free-software tools tied together by a proprietary, 2 RPG. Preface xxi database-centered coordination layer. The tools included GCC, GDB, and a window-based version of Emacs originally called Lucid Emacs and now called Xemacs. The interaction of the suite of tools with the coordination layer was through an open set of protocols, and several compilers were modified to support these protocols. Lucid was one of the first companies to do significant work on open-source code (in this case, Free Software Foundation code) as part of a business strategy, and in fact, the existence of LGPL is partly due to this early commercial use of GPLed code. This book also includes insights from studying other open-source projects such as Linux, Apache, Emacs, Xemacs, GCC, GDB, and Mozilla. We have had experience with projects and companies that were trying to achieve something creative in the context of a passionate user, developer, and partner landscape where the knowledge, expertise, and innovation in that landscape needed to be part of the creativity. Ron Goldman Richard P. Gabrid March, 2005
================================================================================ Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================================================ Apache Tomcat Version 7.0.57 Release Notes ========= CONTENTS: ========= * Dependency Changes * API Stability * JNI Based Applications * Bundled APIs * Web application reloading and static fields in shared libraries * Tomcat on Linux * Enabling SSI and CGI Support * Security manager URLs * Symlinking static resources * Viewing the Tomcat Change Log * Cryptographic software notice * When all else fails =================== Dependency Changes: =================== Tomcat 7.0 is designed to run on Java SE 6 and later. In addition, Tomcat 7.0 uses the Eclipse JDT Java compiler for compiling JSP pages. This means you no longer need to have the complete Java Development Kit (JDK) to run Tomcat, but a Java Runtime Environment (JRE) is sufficient. The Eclipse JDT Java compiler is bundled with the binary Tomcat distributions. Tomcat can also be configured to use the compiler from the JDK to compile JSPs, or any other Java compiler supported by Apache Ant. ============== API Stability: ============== The public interfaces for the following classes are fixed and will not be changed at all during the remaining lifetime of the 7.x series: - javax/**/* The public interfaces for the following classes may be added to in order to resolve bugs and/or add new features. No existing interface will be removed or changed although it may be deprecated. - org/apache/catalina/* - org/apache/catalina/comet/* Note: As Tomcat 7 matures, the above list will be added to. The list is not considered complete at this time. The remaining classes are considered part of the Tomcat internals and may change without notice between point releases. ======================= JNI Based Applications: ======================= Applications that require native libraries must ensure that the libraries have been loaded prior to use. Typically, this is done with a call like: static { System.loadLibrary("path-to-library-file"); } in some class. However, the application must also ensure that the library is not loaded more than once. If the above code were placed in a class inside the web application (i.e. under /WEB-INF/classes or /WEB-INF/lib), and the application were reloaded, the loadLibrary() call would be attempted a second time. To avoid this problem, place classes that load native libraries outside of the web application, and ensure that the loadLibrary() call is executed only once during the lifetime of a particular JVM. ============= Bundled APIs: ============= A standard installation of Tomcat 7.0 makes all of the following APIs available for use by web applications (by placing them in "lib"): * annotations-api.jar (Annotations package) * catalina.jar (Tomcat Catalina implementation) * catalina-ant.jar (Tomcat Catalina Ant tasks) * catalina-ha.jar (High availability package) * catalina-tribes.jar (Group communication) * ecj-4.4.jar (Eclipse JDT Java compiler) * el-api.jar (EL 2.2 API) * jasper.jar (Jasper 2 Compiler and Runtime) * jasper-el.jar (Jasper 2 EL implementation) * jsp-api.jar (JSP 2.2 API) * servlet-api.jar (Servlet 3.0 API) * tomcat7-websocket.jar (WebSocket 1.1 implementation) * tomcat-api.jar (Interfaces shared by Catalina and Jasper) * tomcat-coyote.jar (Tomcat connectors and utility classes) * tomcat-dbcp.jar (package renamed database connection pool based on Commons DBCP) * tomcat-jdbc.jar (Tomcat's database connection pooling solution) * tomcat-util.jar (Various utilities) * websocket-api.jar (WebSocket 1.1 API) You can make additional APIs available to all of your web applications by putting unpacked classes into a "classes" directory (not created by default), or by placing them in JAR files in the "lib" directory. To override the XML parser implementation or interfaces, use the endorsed mechanism of the JVM. The default configuration defines JARs located in "endorsed" as endorsed. ================================================================ Web application reloading and static fields in shared libraries: ================================================================ Some shared libraries (many are part of the JDK) keep references to objects instantiated by the web application. To avoid class loading related problems (ClassCastExceptions, messages indicating that the classloader is stopped, etc.), the shared libraries state should be reinitialized. Something which might help is to avoid putting classes which would be referenced by a shared static field in the web application classloader, and putting them in the shared classloader instead (JARs should be put in the "lib" folder, and classes should be put in the "classes" folder). ================ Tomcat on Linux: ================ GLIBC 2.2 / Linux 2.4 users should define an environment variable: export LD_ASSUME_KERNEL=2.2.5 Redhat Linux 9.0 users should use the following setting to avoid stability problems: export LD_ASSUME_KERNEL=2.4.1 There are some Linux bugs reported against the NIO sendfile behavior, make sure you have a JDK that is up to date, or disable sendfile behavior in the Connector.<br/> 6427312: (fc) FileChannel.transferTo() throws IOException "system call interrupted"<br/> 5103988: (fc) FileChannel.transferTo should return -1 for EAGAIN instead throws IOException<br/> 6253145: (fc) FileChannel.transferTo on Linux fails when going beyond 2GB boundary<br/> 6470086: (fc) FileChannel.transferTo(2147483647, 1, channel) cause "Value too large" exception<br/> ============================= Enabling SSI and CGI Support: ============================= Because of the security risks associated with CGI and SSI available to web applications, these features are disabled by default. To enable and configure CGI support, please see the cgi-howto.html page. To enable and configue SSI support, please see the ssi-howto.html page. ====================== Security manager URLs: ====================== In order to grant security permissions to JARs located inside the web application repository, use URLs of of the following format in your policy file: file:${catalina.base}/webapps/examples/WEB-INF/lib/driver.jar ============================ Symlinking static resources: ============================ By default, Unix symlinks will not work when used in a web application to link resources located outside the web application root directory. This behavior is optional, and the "allowLinking" flag may be used to disable the check. ============================== Viewing the Tomcat Change Log: ============================== See changelog.html in this directory. ============================= Cryptographic software notice ============================= This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See <http://www.wassenaar.org/> for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this Apache Software Foundation distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. The following provides more details on the included cryptographic software: - Tomcat includes code designed to work with JSSE - Tomcat includes code designed to work with OpenSSL ==================== When all else fails: ==================== See the FAQ http://tomcat.apache.org/faq/
智能指针 智能指针shared_ptr的⽤法 的⽤法   为了解决C++内存泄漏的问题,C++11引⼊了智能指针(Smart Pointer)。   智能指针的原理是,接受⼀个申请好的内存地址,构造⼀个保存在栈上的智能指针对象,当程序退出栈的作⽤域范围后,由于栈上的变 量⾃动被销毁,智能指针内部保存的内存也就被释放掉了(除⾮将智能指针保存起来)。   C++11提供了三种智能指针std::shared_ptr, std::unique_ptr, std::weak_ptr,使⽤时需添加头⽂件<memory>。   shared_ptr使⽤引⽤计数,每⼀个shared_ptr的拷贝都指向相同的内存。每使⽤他⼀次,内部的引⽤计数加1,每析构⼀次,内部的引⽤ 计数减1,减为0时,删除所指向的堆内存。shared_ptr内部的引⽤计数是安全的,但是对象的读取需要加锁。 1. shared_ptr的基本⽤法 初始化   可以通过构造函数、std::make_shared<T>辅助函数和reset⽅法来初始化shared_ptr: #include "stdafx.h" #include <iostream> #include <future> #include <thread> using namespace std; class Person { public: Person(int v) { value = v; std::cout << "Cons" <<value<< std::endl; } ~Person() { std::cout << "Des" <<value<< std::endl; } int value; }; int main() { std::shared_ptr<Person> p1(new Person(1));// Person(1)的引⽤计数为1 std::shared_ptr<Person> p2 = std::make_shared<Person>(2); p1.reset(new Person(3));// ⾸先⽣成新对象,然后引⽤计数减1,引⽤计数为0,故析构Person(1) // 最后将新对象的指针交给智能指针 std::shared_ptr<Person> p3 = p1;//现在p1和p3同时指向Person(3),Person(3)的引⽤计数为2 p1.reset();//Person(3)的引⽤计数为1 p3.reset();//Person(3)的引⽤计数为0,析构Person(3) return 0; }   注意,不能将⼀个原始指针直接赋值给⼀个智能指针,如下所⽰,原因是⼀个是类,⼀个是指针。 std::shared_ptr<int> p4 = new int(1);// error   reset()包含两个操作。当智能指针中有值的时候,调⽤reset()会使引⽤计数减1.当调⽤reset(new xxx())重新赋值时,智能指针⾸先是⽣ 成新对象,然后将就对象的引⽤计数减1(当然,如果发现引⽤计数为0时,则析构旧对象),然后将新对象的指针交给智能指针保管。 获取原始指针   std::shared_ptr<int> p4(new int(5)); int *pInt = p4.get(); 指定删除器   智能指针可以指定删除器,当智能指针的引⽤计数为0时,⾃动调⽤指定的删除器来释放内存。std::shared_ptr可以指定删除器的⼀个原 因是其默认删除器不⽀持数组对象,这⼀点需要注意。   2. 使⽤shared_ptr需要注意的问题   但凡⼀些⾼级的⽤法,使⽤时都有不少陷阱。 不要⽤⼀个原始指针初始化多个shared_ptr,原因在于,会造成⼆次销毁,如下所⽰: int *p5 = new int; std::shared_ptr<int> p6(p5); std::shared_ptr<int> p7(p5);// logic error 不要在函数实参中创建shared_ptr。因为C++的函数参数的计算顺序在不同的编译器下是不同的。正确的做法是先创建好,然后再传 ⼊。 function(shared_ptr<int>(new int), g()); 禁⽌通过shared_from_this()返回this指针,这样做可能也会造成⼆次析构。 避免循环引⽤。智能指针最⼤的⼀个陷阱是循环引⽤,循环引⽤会导致内存泄漏。解决⽅法是AStruct或BStruct改为weak_ptr。 struct AStruct; struct BStruct; struct AStruct { std::shared_ptr<BStruct> bPtr; ~AStruct() {
shared_ptr智能指针)举例 程序使⽤动态内存出于以下三种原因之⼀ : 1、程序不知道⾃⼰需要多少对象; 2、程序不知道所需对象的准确类型; 3、程序需要在多个对象间共享数据 ⼀. 要确保⽤ new 动态分配的内存空间在程序的各条执⾏路径都能被释放是⼀件⿇烦的事情。 11 模板库的 <memory> 头⽂件中定义的智能, 即 shared _ptr 模板,就是⽤来部分解决这个问题的。 只要将 new 运算符返回的指针 p 交给⼀个 shared_ptr 对象"托管",就不必担⼼在哪⾥写delete p语句——实际上根本不需要编写这条 语句,托管 p 的 shared_ptr 对象在消亡时会⾃动执⾏delete p。⽽且,该 shared_ptr 对象能像指针 p —样使⽤,即假设托管 p 的 shared_ptr 对象叫作 ptr,那么 *ptr 就是 p 指向的对象。 通过 shared_ptr 的构造函数,可以让 shared_ptr 对象托管⼀个 new 运算符返回的指针,写法如下: 此后,ptr 就可以像 T* 类型的指针⼀样使⽤,即 *ptr 就是⽤ new 动态分配的那个对象。 多个 shared_ptr 对象可以共同托管⼀个指针 p,当所有曾经托管 p 的 shared_ptr 对象都解除了对其的托管时,就会执⾏delete p。 初始化: 例1 例2 只有指向动态分配的对象的指针才能交给 shared_ptr 对象托管。将指向普通局部变量、全局变量的指针交给 shared_ptr 托管,编译时不 会有问题,但程序运⾏时会出错,因为不能析构⼀个并没有指向动态分配的内存空间的指针。 ⼆. shared_ptrmake_shared区别 make_shared 在动态内存中分配⼀个对象并初始化它,返回指向此对象的shared_ptr,与智能指针⼀样,make_shared也定义在头⽂件 memory中。 当要⽤make_shared时,必须指定想要创建的对象类型,定义⽅式与模板类相同,在函数名之后跟⼀个尖括号,在其中给出类型。 如 std::shared_ptr<int> p1 = std::make_shared<int>(66); ⼀般采⽤auto定义⼀个对象来保存make_shared的结果,如 auto p2 = std::make_shared<int>(88); 例
C++智能指针shared_ptr⽤法详解 C++智能指针shared_ptr⽤法详解 shared_ptrC++11⾥的新特性,其包装了new操作符在堆上分配的动态对象。如: shared_ptr<int> sp1(new int(100)); //相当于 //int *sp1=new int(100); //auto sp1=make_shared<int>(100); 它与普通指针相⽐,最⼤的不同点就是shared_ptr是⼀个类,当对象⽣命周期结束时,会⾃动调⽤其析构函数,释放内存。⽽不再需要程 序员显⽰地调⽤delete关键字。 同时,shared_ptr重载了"*"和"->"操作符以模仿原始指针的⾏为,并且提供了显⽰bool类型转换以判断指针的有效性。 shared_ptr<int> sp1(new int(100)); assert(sp1); *sp1=200; shared_ptr<string> sp2(new string("Hello")); assert(sp2->size()==5); 我们还可以使⽤shared_ptr的成员函数get()获取原始指针 shared_ptr<int> sp1(new int(100)); int *Int_ptr=sp1.get(); shared_ptr⾥的reset()函数 shared_ptr⾥有个成员函数use_count(),⽤于返回该对象的引⽤计数。 shared_ptr<int> sp1(new int(100)); cout<<"当前计数: "<<sp1.use_count()<<endl; auto sp2=sp1; cout<<"当前计数: "<<sp1.use_count()<<endl; { auto sp3=sp2; cout<<"当前计数: "<<sp1.use_count()<<endl; } cout<<"当前计数: "<<sp1.use_count()<<endl; 当⼀个shared_ptr对象调⽤reset()函数时,它的作⽤时将引⽤计数减⼀,调⽤本⾝的对象的引⽤计数变为0. shared_ptr<int> sp1(new int(100)); cout<<"当前计数: "<<sp1.use_count()<<endl; auto sp2=sp1; cout<<"当前计数: "<<sp1.use_count()<<endl; { auto sp3=sp2; cout<<"当前计数: "<<sp1.use_count()<<endl; } cout<<"当前计数: "<<sp1.use_count()<<endl; sp2.reset();//这⾥换成sp1.reset(),可以发现sp2的计数为1,sp1的计数为0. cout << "sp2当前计数: " << sp2.use_count() << endl; cout << "sp1当前计数: " << sp2.use_count() << endl; 上⾯代码运⾏后,sp2的计数为0,sp1的计数为1。若将sp2.reset()换位sp1.reset(),则sp2的计数为1,sp1的计数为0。 在每次对shared_ptr进⾏拷贝或者赋值的时候,都会使计数加1。 ⼯⼚函数 每次使⽤shared_ptr都需要显⽰的使⽤new关键字创建⼀个对象。固std库提供了⼀个⼯⼚函数make_shared()。 ⽤法: auto sp1=make_shared<int>(100); //相当于 shared_ptr<int> sp1(new int(100)); make_shared是⼀个泛型,<>⾥⾯为数据类型,()对应着new()⾥的东西,其返回值是⼀个shared_ptr类型的变量。 定制删除器 shared_ptr的构造函数可有多个参数,其中有⼀个是shared_ptr(Y *p,D d),第⼀个参数是要被管理的指针,它的含义与其构造函数的参 数相同。⽽第⼆个参数则告诉shared_ptr在析构时不要使⽤delete来操作指针p,⽽要⽤d来操作,即把delete p 换成d(p)。因此,我们 就可以⾃⼰制作⼀个删除器 如:对于传统的struct FILE的C⽂件操作,需要 FILE *fp=fopen("./1.txt","r"); //... //... fclose(fp); 若⽤shared_ptr,则可以这样做: shared_ptr<FILE> fp(fopen("./1.txt","r"), fclose); 离开作⽤域时,shared_ptr会⾃动调⽤fclose()函数关闭⽂件。
make_sharednew在分配和初始化动态内存时有一些区别make_shared在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。它可以通过传递参数给构造函数来初始化对象。make_shared定义在头文件memory中。它的优点是可以减少内存分配和对象构造的次数,提高性能。同时,make_shared还可以自动销毁对象并释放内存,无需手动管理。 而new则是用于在动态内存中分配一个对象,并返回指向该对象的指针。使用new需要手动管理内存,包括手动析构对象和释放内存。它需要使用delete或delete[]来释放对象和内存。new可以用于分配单个对象,也可以用于分配数组。但是new分配的内存可能会导致内存碎片产生。 总结来说,make_shared可以简化动态内存分配和对象初始化的过程,并且自动管理内存的释放。而new需要手动管理内存,并且可能导致内存碎片的产生。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [shared-ptr智能指针)举例.pdf](https://download.csdn.net/download/qq_43934844/87504633)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [[modern c++] std::make_sharedstd::shared(new)的区别](https://blog.csdn.net/ykun089/article/details/121787439)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [newmake_shared 在内存上的区别](https://blog.csdn.net/anna2117/article/details/101802846)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值