精华内容
下载资源
问答
  • 一、auto_ptr和shared_ptr作为普通参数指针参数  我想这是我们使用最多的,直接传过去好了,基本上没什么好担心的。例如:  1.  T* pt = new T;   auto_ptr ap( pt);  // void f1(auto_ptr ap);  f1...

    一、auto_ptr和shared_ptr作为普通参数、指针参数

            我想这是我们使用最多的,直接传过去好了,基本上没什么好担心的。例如:

            1.

            T* pt = new T;     
          auto_ptr<T> ap( pt);

            // void f1(auto_ptr<T> ap);

            f1(ap);

            //  ap 为 empty(空)了


            // void f2(T* pt);

            f2(ap.get()); 

            //  ap还拥有所有权。

           唯一要注意的是,auto_ptr是独占的,一旦赋值给别人后,就把所有权也交给别人了,自己就是一个空指针了,不能再使用了。详细请看stl文档或stl标准程序库。


            2.

            shared_ptr<T> sp(new T);

            // void f1(shared_ptr<T> sp);

            f1(sp);

            //  sp还可以继续使用,引用计数型


            // void f2(T* pt);

            f2(sp.get()); 


    二、关于线程

            auto_ptr的拥有权只有一份,所以不适合赋值给多个线程。shared_ptr是线程安全的,没有问题。

            如果你用boost里面的线程,用boost::function函数对象用shared_ptr还是很简单的。


            如果用_beginthreadex和UINT __stdcall threadRun(LPVOID lpParam),哥求你,放弃这种使用方式吧。我现在很不喜欢这种使用方式,太古板了。如果你要在这种方式下使用智能指针赋值给LPVOID,那使用就稍微麻烦一点。

            auto_ptr就不讲了,因为所有权的问题不建议给赋值给线程参数,如果要使用,请借鉴后面赋值给WPARAM。

            shared_ptr网上有一个思路是对的,但有严重缺陷的方式:http://stackoverflow.com/questions/5102038/how-can-i-pass-boostshared-ptr-as-a-pointer-to-a-windows-thread-function?rq=1

            test::start()
            {
                ....
                shared_ptr<test> shPtr = shared_from_this();
                boost::weak_ptr<test> wPtr=shPtr;
                _beginthreadex( NULL, 0, &test::threadRun, &wPtr, 0, &threadID );
                ...
            }


            /*this is a static function*/
            UINT __stdcall test::threadRun( LPVOID lpParam )
            { 
                    shared_ptr<test> k      = static_cast< boost::weak_ptr<test>* >(lpParam)->lock();
                 ...
            }

           使用boost::weak_ptr的思路是很正确的,但是这样传&wPtr是很有问题的。必须用其他方式包装或传递shared_ptr。


    三、PostMessage中智能指针传给WPARAM

            最近一个项目中,要把一个结构通过PostMessage传给界面线程。这个结构数据当然是临时生成的,我这个工作线程对界面线程一无所知,只能通过发消息通知,boost里面的回调函数和信号事件无效。因为有个使用别人的控件窗口只能界面线程调用才显示,我也是用boost里面函数和回调不显示郁闷了很久,后来排除一切不可能因素才认定是工作线程非界面线程原因。

            直接使用new是一件很头疼的事,因为释放是一件很麻烦的事,基本上不能遵守谁申请谁释放,因为我只负责把数据产生出来交给调用者,调用者的情况完全不知。  

            shared_ptr用的多,那就还是用只能指针吧。shared_ptr方式,完全可以参考上面的“二、关于线程”,用boost::weak_ptr辅助。

            当然我用了auto_ptr,因为我觉得auto_ptr更符合我这里使用情况,把所有权转交给别人,自己就不管了。而且还不需要辅助指针weak_ptr

            下面介绍使用方式:

            发送者:

            std::auto_ptr<T> apMessage(newT());

            if (PostMessage(WM_SHOW_MESSAGE, (WPARAM)apMessage.get(), ID_***))
            {
                    // 释放控制权
                    apMessage.release();
           }     


            接收者:

            std::auto_ptr<T> apShowMessage(reinterpret_cast<T*>(wParam));


            唯一要注意的是,发送者要释放控制权,不然,接收者无法重新包装成auto_ptr,我刚开始犯过这样的错误。表面上好像成功了,但是由于发送者并没有释放控制权即所有权,所以接收者并不能使用新包装的auto_ptr(表面上可以得到指针,由于异步,发送者并没有转交所有权,PostMessage后就释放内存了,接收者得到的是一个野指针)

    所以需要发送者在发送成功后释放控制权,让接收者重新包装成auto_ptr,得到其所有权。


    展开全文
  • 1.考虑这样的processWidget函数声明: void processWidget(shared_ptr pw, int priority);当我们采取这样的方式调用: processWidget(new Widget, priority());显然是不能编译通过的,因为shared_ptr不接受通过new...

    1.考虑这样的processWidget函数声明:

    void processWidget(shared_ptr<Widget> pw, int priority);
    当我们采取这样的方式调用:

    processWidget(new Widget, priority());
    显然是不能编译通过的,因为shared_ptr不接受通过new指针隐式的构造(explicit)

    所以这样写就能通过编译:

    processWidget(shared_ptr<Widget>(new Widget), priority())
    此时虽然能够通过编译,但是仍然存在一个隐形的资源泄露问题。因为C++编译器对new Widget, shared_ptr构造函数, priority函数调用这三者次序不定,所以当执行顺序为1>new widget 2>priority() 3>shared_ptr构造函数时,第二步发生异常,那么第一步申请的内存就造成泄露。解决办法是用独立语句来把对象放入智能指针:

    shared_ptr<Widget> pw(new Widget);
    processWidget(pw, priority());

    2. 考虑这样的函数声明:

    process(shared_ptr<int> ptr);
    process函数参数采取值传递方式,因此实参会被拷贝到ptr中。这样在函数运行过程中,引用计数至少为2。当process结束时,ptr引用计数会递减,但不会变为0.因此当局部变量ptr被销毁时,ptr指向的内存不会被释放。

    使用此函数的正确方法:

    shared_ptr<int> p(new int(42));
    process(p);
    虽然不能直接传递一个内置指针,但是可以传递一个临时的shared_ptr, 考虑如下调用:

    int *x(new int(1024));
    process(shared_ptr<int>(x));
    结果是经由x指针申请的内存,在process函数处理结束之后被销毁了。但x继续指向已经释放的内存,从而变成一个野指针。当将一个shared_ptr绑定到一个普通指针时,我们就将内存的管理责任交给了这个shared_ptr。一旦这样做了,我们就不应该再使用内置指针来访问shared_ptr所指向的内存了。














    展开全文
  • 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、pandas是什么? 示例:pandas...


    常见问题

    指针作为函数参数时,参数是如何传递的
    指针作为函数参数时,malloc函数返回动态内存问题

    这一类问题我们经常会遇见,不注意的话很容易出错。并且对函数传参不是特别熟悉的话,理解起来很费劲。下面仔细分析一下这一类问题。


    一、函数参数传递

    在c语言中实参和形参之间的数据传输是单向的“值传递”方式,也就是实参可以影响形参,而形参不能影响实参。指针变量作为参数也不例外,但是可以改变实参指针变量所指向的变量的值。
    这一段文字解释对于很多初学者(包括博主自己)来说,是很难理解的,因此,我们只有多分析代码,从具体的代码中去掌握。

    1.1普通值作为函数参数

    // 普通值传递
    #include <stdio.h>
    
    void test(int num)
    {
        num = 5;
        printf("in function test, num = %d\n",num);
    }
    
    int main(int argc, char* argv[])
    {
        int num = 9;
        test(num);
        printf("in function main, num = %d\n",num);                                                                                                    
        return 0;
    }
    

    在这里插入图片描述
    在test函数内部,修改num的值,对实参num并无影响,即test函数接收到的实际上是外层num的一个拷贝。普通值作为函数参数时很容易理解,这里就不废话了。

    1.2指针作为函数参数(一级指针)

    示例1

    //一级指针作为函数参数                                                                                                                             
    #include <stdio.h>
    
    void test(char *p) 
    {
        p = "hello world";
        printf("str = %s\n",p);
    }
    
    int main()
    {
        char *str = NULL;
        test(str);
        printf("str = %s\n",str);
        return 0;
    }
    

    在这里插入图片描述
    我们可能会认为主函数输出结果是hello world,但实际上调用函数test并没有改变指针str的值,我们通过框图来分析一下整个代码的运行过程
    在这里插入图片描述
    主函数中指针str指向null,调用函数test,指针str的值(也就是null的地址)传递给指针string,指针string也指向了null,接着字符串“hello world”的地址传给string,指针string指向了“hello world”的地址,函数调用结束后,“hello world”内存释放。我们发现主函数中指针str始终指向null这个地址,而null这个地址中的内容自始至终没有被修改过。

    为了更好的理解,我们打印一些信息:

    #include <stdio.h>
    
    void test(char *string)
    {
        printf("string操作之前的指针:%p\n",string);
        string = "hello world";
        printf("string操作之后的指针:%p\n",string);
        printf("string = %s\n",string);
    }
    
    int main()
    {                                                                                                                                                  
        char *str = NULL;
        printf("传入test函数之前str的指针:%p\n",str);
        test(str);
        printf("传入test函数之后str的指针:%p\n",str);
        printf("str = %s\n",str);
        return 0;
    }
    
    

    在这里插入图片描述
    示例2

    #include <stdio.h>
    #include <string.h>
    
    void test(char *string)
    {
        char *testString = "world";
    
        printf("222 string addr:%p,   testString addr:%p\n",string,testString);
    
        string = testString;
        printf("333 string addr:%p,   testString addr:%p\n",string,testString);
    }
    
    int main(void)
    {
        char *str ="china";
        printf("111 str addr:   %p,   str is:%s\n",str,str);
    
        test(str);
        printf("444 str addr:   %p,   str is:%s\n",str,str);
        
        return 0;
    }  
    

    在这里插入图片描述
    框图表示代码运行过程
    在这里插入图片描述
    我们将上面代码修改一下:

    #include <stdio.h>
    #include <string.h>
    
    void test(char *string)
    {
        printf("222 addr:%p, content:%s\n",string,string);
        strcpy(string,"world");
        printf("333 addr:%p, content:%s\n",string,string);  
    }
    
    int main(void)
    {
        char *str ="china";
        printf("111 addr:%p, content:%s\n",str,str);
    
        test(str);
        printf("444 addr:%p, content:%s\n",str,str);
            
        return 0;
    } 
    

    在这里插入图片描述
    分析不难发现是strcpy函数那里发生了非法内存访问,造成了段错误,原因是因为主函数中指针str指向了一个字符串常量“China”,它位于代码段(text段),因此,调用函数时,尝试去修改它是不允许的,会产生段错误。

    那么,我们再次进行修改:

    #include <stdio.h>
    #include <string.h>
    
    void test(char *string)
    {
        printf("222 addr:%p, content:%s\n",string,string);
        strcpy(string,"world");
        printf("333 addr:%p, content:%s\n",string,string);  
    }
    
    int main(void)
    {
        char str[] ="china";  //定义为字符数组
        printf("111 addr:%p, content:%s\n",str,str);
    
        test(str);
        printf("444 addr:%p, content:%s\n",str,str);
            
        return 0;
    } 
    

    在这里插入图片描述
    我们发现主函数中指针str的内容被修改了,这是怎么回事呢?结合前面的分析框图,这里应该自己可以分析理解了。

    总结:
    函数的参数是指针时,在被调用的函数中
    1.改变指针的值,不会改变实参的值。
    2.改变指针指向的内容时,会改变实参的值。
    注意:在传递的过程中如果是const类型的指针是不允许修改的。

    1.3返回指针和二级指针

    那么我们要改变主函数中str指针指向的地址应该怎么办呢?

    两种办法
    1.在函数内部对指针进行操作后 ,返回该指针
    2.二级指针或指针的引用传递(c++)

    返回指针的方法:

    #include <stdio.h>
    
    char *test(char *string)
    {
        string = "hello world";
        printf("string addr:%p,      string = %s\n",string,string);
        return string;
    }
    
    int main()
    {
        char *str = NULL;
        printf("str    addr:%p,      str    = %s\n",str,str);                                                                                          
    
        str = test(str);
        printf("str    addr:%p,      str    = %s\n",str,str);
        return 0;
    }
    

    在这里插入图片描述

    二级指针:

    #include <stdio.h>
    
    void test(char **string)
    {
        *string = "hello world";
    }
    
    int main()
    {
        char *str = NULL;
        test(&str);
        printf("str=%s\n",str);
        return 0;
    } 
    

    在这里插入图片描述
    具体过程见:C语言指针作为函数参数传递学习(一)

    二、malloc返回动态内存问题

    我们先来看两段代码(实际上是相同的代码)

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void getmemory(char *p) 
    {
    	p = (char *) malloc(100);
    	strcpy(p,"hello world");
    }
    
    int main( )
    {
    	char *str = NULL;
    	getmemory(str);
    	printf("str = %s\n",str);
      
      	free(str);
      	return 0;
    } 
    

    在这里插入图片描述

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    void getMemory(char *p,int num)
    {
        p = (char*)malloc(num);
    }
    
    int main()
    {
        char *str = NULL;
        getMemory(str,100);
        strcpy(str,"hello");
    
        printf("str = %s",str);
        return 0;
    } 
    

    在这里插入图片描述
    我们发现上面两段代码执行时都会发生段错误。上面一段代码是因为getmemory函数中申请的动态内存没有返回给str,free函数对str操作出现了段错误;下面一段代码也是因为getmemory函数中申请的动态内存没有返回给str,strcpy函数操作出现了非法内存访问,造成段错误。两段代码段错误的本质是一样的,分析过前面的几段代码之后,我们就很容易理解问题所在了。

    void getMemory(char * p, int num)中的指针p实际上是主函数中str的一个副本,编译器总是要为函数的每个参数制作临时副本。在本例中,p申请了新的内存,只是把p所指向的内存地址改变了,但是str丝毫未变。因为函数getMemory没有返回值,因此str并不指向p所申请的那段内存,所以函数getMemory并不能输出任何东西,如下框图所示:
    在这里插入图片描述

    如果一定要用指针参数去申请内存,那么应该采用指向指针的指针,传str的地址给函数getMemory。代码如下:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    void getMemory(char **p,int num)
    {
    	*p = (char*)malloc(num);
    }
    
    int main()
    {
    	char *str = NULL;
    	getMemory(&str,100);
    	strcpy(str,"hello");
    	printf("str = %s\n",str);
    	return 0;
    }
    

    在这里插入图片描述
    由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。这种方法更简单,代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char* getMemory(char *p, int num)
    {
          p = (char*)malloc(sizeof(char) * num);
          return p;
    }
    
    int main()
    {
          char *str = NULL;
          str = getMemory(str, 100);
          strcpy(str, "hello");
    
          printf("str = %s\n",str);                                                                                                                    
          return 0;
    }
    

    在这里插入图片描述

    三、致谢

    参考博文:
    C语言指针作为函数参数传递学习(一)
    传递动态内存时的若干问题
    感谢以上两位博主提供的帮助,读者如有疑问,可参考以上两篇博客。

    展开全文
  • 智能指针(shared_ptr,unique_ptr)作为函数参数或者返回值时的...当智能指针作为函数的参数或者返回值时,一直在纠结到底是用智能指针对象本身还是用原始指针。Herb Sutter大师的文章很好的解决了这个疑惑,参见网址: ...

    智能指针(shared_ptr,unique_ptr)作为函数参数或者返回值时的一些注意事项

     

    当智能指针作为函数的参数或者返回值时,一直在纠结到底是用智能指针对象本身还是用原始指针。Herb Sutter大师的文章很好的解决了这个疑惑,参见网址:

    https://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/

           总结起来如下

    1、 不要传递shared_ptr本身,而是用原始指针。因为会有性能损失,原子操作的自增自减等。

    使用f(widget *w)

    不使用f(shared_ptr< widget > w)

    函数的返回值也是同样的道理。

    2当表示所有权的转移时,用unique_ptr作为函数参数。

     

    Guideline: Don’t pass a smart pointer as a function parameter unless you want to use or manipulate the smart pointer itself, such as to share or transfer ownership.

     

    Guideline: Prefer passing objects by value, *, or &, not by smart pointer.

     

    Guideline: Express a “sink” function using a by-value unique_ptr parameter.

     

    Guideline: Use a non-const unique_ptr& parameter only to modify the unique_ptr.

     

    Guideline: Don’t use a const unique_ptr& as a parameter; use widget* instead.

     

    Guideline: Express that a function will store and share ownership of a heap object using a by-value shared_ptr parameter.

     

    Guideline: Use a non-const shared_ptr& parameter only to modify the shared_ptr. Use a const shared_ptr& as a parameter only if you’re not sure whether or not you’ll take a copy and share ownership; otherwise use widget* instead (or if not nullable, a widget&).

    转载于:https://www.cnblogs.com/ljy339/p/11435265.html

    展开全文
  • 智能指针作为线程参数 #include #include #include #include using namespace std; void myprint2( unique_ptr<int>pmybuf) { } int main() { unique_ptr<int> myp(new int(122)); thread mytobj...
  • 结论: 当传递一个类对象作为线程参数时,不论是用字面值接受,还是用引用接受, thread()都会将这个对象...thread()+detach():给子线程传递参数时,使用临时对象作为参数,子线程函数参数在主线程退出前构造出来,最后...
  • 智能指针

    2019-09-03 23:20:06
    智能指针   智能指针是一个类,这个类的构造...所有的智能指针类都有一个explicit构造函数,以指针作为参数。因此不能自动将指针转换为智能指针对象,必须显式调用: shared_ptr<double> pd; double *...
  • CCmdLookAheadPlannerResultPtr ptrCmdLookAheadPlannerResult;//声明智能指针,但是先不分配内存和地址 demo_singleMovelPlan... //作为函数参数,用来输出 int demo_singleMovelPlan(CCmdLookAheadPlanner...
  • lambda函数本质: 遵循了类的特征,生命周期和类是一样的 ...还有一个弊端也改变了外部函数接口,上面例子必须要传入智能指针。。 智能指针有传染性,一个地方要用智能指针,很多地方都被迫用智能指针 ...
  • 当表示所有权的转移时,可以使用unique_ptr作为函数参数。正是因为c++11的右值引用和move语义,才给了c++创造智能指针的条件。std::move实际上就是将左值转化为右值引用&&,其实就是一个static_cast<T&...
  • C++智能指针

    2018-11-23 11:41:24
    STL一共给我们提供了4种智能指针:...),以指针作为参数。比如auto_ptr的类的模板原型为: 因此,不能自动将指针转换为智能指针对象,“必须显示调用”,例子如下: 对于智能指针都应该避免一点: 即:不要将“...
  • C++ 智能指针

    2018-07-26 19:33:48
    首先明确C++ 智能指针本身不是指针,而是一个类,这个类构建的时候是用指针作为参数传递进入,在使用的时候可以用起来像指针一样使用,感觉最主要的功能是完成了指针所指向原始对象的内存管理,当对象最后生命周期...
  • 之前简单的列举了一下各种智能指针的特点,其中提到了这个历经沧桑的指针,C++98中引入,C++11中弃用,C++17中被移除,弃用的原因主要是使用不当容易造成内存崩溃,不能够作为函数的返回值和函数的参数,也不能在...
  • 智能指针(二):shared_ptr浅析

    千次阅读 2018-08-18 13:17:17
    前言 这个指针近乎完美,原来出现在boost库中,C++11时引入了标准库,解决...这种采用引用计数方式避免了对象所有权转移,所以作为函数返回值,函数参数,容器的元素都不会有问题,但是因为引用计数的加入,相应的...
  • C++智能指针简单介绍

    2021-01-18 09:26:48
    STL一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr和weak_ptr(本文章暂...使用注意点 - 所有的智能指针类都有一个explicit构造函数,以指针作为参数。比如auto_ptr的类模板原型为: templet<cla
  • c++ set容器存储指针,智能指针用法

    千次阅读 2018-12-29 12:04:25
    c++ set容器存储指针,智能指针用法Set容器存储c++内置变量Set容器存储指向类对象的智能智能对象 Set容器存储c++内置变量 set容器存储基础变量像int,char,或者是string对象,我们不需要去写比较函数,但是如果存储的...
  • 1)如果指针作为类成员时,使用shared_ptr封装原始指针,解决了复制类对象出现的问题(相较原始指针)。  如果是非内存资源(比如:互斥器),可以在构造时再传一个删除器(deleter)参数(shared_ptr可以,auto_...
  • 每一个 intrusive_ptr 实例都会通过对函数 intrusive_ptr_add_ref 的调用来增加引用计数,并将指针作为参数传递给它。同样,当intrusive_ptr实例被销毁时,它会调用intrusive_ptr_release函数;当对象的引用计数为...
  • c++智能指针之auto_ptr

    2020-11-20 15:56:20
    1.简介 ​ auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一...1] 将已存在的指向动态内存的普通指针作为参数来构造 int* p = new int(33); auto_ptr<
  • C++智能指针之auto_ptr

    2013-04-21 17:44:00
    比如作为函数参数传递时,会丧失所有权。 get() 获取原始指针 release() 释放auto_ptr并返回原始指针 reset(X*) 释放对象并为auto_ptr设置新值 operator* 解引用对象 operator-> 解引用对象成员 operator...
  • 在我的接口实现类中有一个线程函数,我传了一个this指针作为线程函数参数,而我在使用的时候不经意的就把这个this指针赋值给了接口智能指针,于是这个引用计数多Release了一次。要对自己的每一行代码负责。
  • 智能指针(shared_ptr的实现)

    千次阅读 2019-01-04 15:48:03
    1.实现原理:shared_ptr是利用一个计数器,无论我们使用拷贝构造函数、赋值运算符重载、作为函数返回值、或作为参数传给一个参数时计数器+1, 当shared_ptr被赋予一个新值或者需要销毁时,计数器–,直到计数器为0时...
  • STL一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr和weak_ptr ...所有的智能指针类都有一个explicit构造函数,以指针作为参数。比如auto_ptr的类模板原型为: templetclass T> class a
  • /* auto_ptr是智能指引,... auto_ptr赋值用引起所有权的交接,作为函数参数或返回值都会引起所有权的交接。 auto_ptr必须显示初始化 auto_ptr<int> p(new int(43)) //ok auto_ptr<int> p = new...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 146
精华内容 58
关键字:

智能指针作为函数参数