精华内容
下载资源
问答
  • swap函数

    千次阅读 多人点赞 2019-02-25 17:23:02
    C语言如何使用swap函数交换两个值 这是我做过的一道笔试题,一开始我觉得答案是5,10,world hello,hello world;当我编译后才发现错了。 最后百度才发现原来是把SWAP函数的形参和实参搞混了。 当交换的是两个int型...

    C语言如何使用swap函数交换两个值
    在这里插入图首先我们片描述
    这是我做过的一道笔试题,一开始我觉得答案是5,10,world hello,hello world;当我编译后才发现错了。
    最后百度才发现原来是把SWAP函数的形参和实参搞混了。
    当交换的是两个int型值时,实参应该取变量的地址:即swap(&a,&b),然后在swap函数形参应该是int *指针。
    最后就是实参是char *指针时,实参应该取地址,即swap(&str_a,&str_p);这样形参就应该是二级指针。即swap(char **a,char **b);
    这样就交换成功了。
    第一次发,表达有点混乱,见谅!

    展开全文
  • Swap函数

    千次阅读 2012-12-27 22:22:35
    请分别用C++,C#和Java实现一个参数为原始类型的交换函数。 小明想了想,这还不简单,于是在草稿纸上画了起来: 首先是C++: template void swap(T* a,T* b) { T temp; temp = *a; *a = *b; *b = ...


    一天,小明去一家IT公司应聘,面试官给他出了一个很简单的题目:


    请分别用C++,C#和Java实现一个参数为原始类型的交换函数。


    小明想了想,这还不简单,于是在草稿纸上画了起来:


    首先是C++:

    template<class T>
    void swap(T* a,T* b)
    {
    	T temp;
    	temp = *a;
    	*a = *b;
    	*b = temp;
    }
    
    

    然后是C#:

            public void swap<T>(ref T a, ref T b)
            {
                T temp;
                temp = a;
                a = b;
                b = temp;
            }

    最后是Java,等等,Java方法参数不是只支持值传递吗?因此,不可能在方法里改变原始类型变量的值的!!

    没办法,只有写道:

    无法在Java中实现该函数。


    如果放宽界限,允许为引用类型。那么可以这样实现:


    class Holder<T> {
    	public T value = null;
    
    	public Holder(T v) {
    		this.value = v;
    	}
    }
    
    	public static <T> void swap(Holder<T> a, Holder<T> b) {
    		T temp = a.value;
    		a.value = b.value;
    		b.value = temp;
    	}

    Over...

    展开全文
  • 1.默认swap函数所带来的效率问题swap函数用于将两个对象的值相互交换,默认情况下,交换动作可由STL提供的swap算法完成。其典型的实现如下所示:namespacestd{template<typenameT>voidswap(T&a...

    272e2e3792539883e391fce0640da0ab.gif点蓝色字关注“CurryCoder的程序”

    微信公众号:CurryCoder的程序人生
    欢迎关注我,一起学习,一起进步!

    8266a7b746a15a1abbb7c068805f22cd.png


    1.默认swap函数所带来的效率问题

    swap函数用于将两个对象的值相互交换,默认情况下,交换动作可由STL提供的swap算法完成。其典型的实现如下所示:
    namespace std{
        template<typename T>
        void swap(T& a, T& b){
            temp(a);
            a = b;
            b = temp;
        }
    }
    只要类型T支持拷贝(即通过拷贝构造函数和赋值运算符重载完成),默认的swap函数就会帮你交换类型为T的对象。但对某些类型来说,三个对象之间的拷贝没有必要,因为它会影响程序执行的效率其中,最主要的就是“以指针指向一个对象,内含真正数据”的那种类型。这种设计的常见形式是所谓的pimpl手法。如下例所示:
    class WidgetImpl{  // 针对Widget数据而设计的类
    public:
        // ...
    private:
        int a, b, c;  
        std::vector<double> v; // 可能有很多数据,意味着拷贝时间很久
        // ...
    };

    class Widget{  // 该类使用pimpl手法
    public:
        Widget(const Widget& rhs);
        Widget& operator=(const Widget& rhs){
            // ...
            *pImpl = *(rhs.pImpl);   // 复制Widget时,令其拷贝其WidgetImpl对象
            // ...
        }
        // ...
    private:
        WidgetImpl* pImpl;
    };
    一旦需要交换两个Widget对象值,唯一需要的就是交换其pImpl指针,但默认的swap函数不知道这点。它不仅仅拷贝三个Widget对象,还拷贝了三个WidgetImpl对象。因此,默认swap函数非常缺乏效率。

    2.对std::swap进行特化定制

    我们希望告诉std::swap,当Widget对象被交换时,真正该交换的是其内部的pImpl指针。因此,我们需要将std::swap进行定制,得到特化版本的swap函数。如下面代码段所示,但下面的形式仍无法通过编译。
    // 这是std::swap针对T是Widget的特化版本,目前还无法通过编译。
    namespace std{
        template<>    // 表示它是std::swap的一个特化版本
        void swap (Widget& a, Widget& b){  // swap表示这个特化版本是针对T为Widget设计的
            swap(a.pImpl, b.pImpl);  // 交换Widget对象时,只有交换它们的pImpl指针即可
        }
    }
    通常情况下,我们不可以改变std命名空间中的任何东西,但是可以为标准模板(如swap函数)制定特化版本,让它成为专属于我们自己的类。上面代码段中的特化版本swap函数是无法通过编译的,这是因为它企图访问a和b内的pImpl指针,而该指针是私有的。解决方法令Widget声明一个名为swap的公有成员函数,让其完成真正的交换工作,然后将std::swap特化,令它调用该成员函数。改进后的代码如下所示:
    class WidgetImpl{  // 针对Widget数据而设计的类
    public:
        // ...
    private:
        int a, b, c;  
        std::vector<double> v; // 可能有很多数据,意味着拷贝时间很久
        // ...
    };

    class Widget{  // 该类使用pimpl手法
    public:
        Widget(const Widget& rhs);
        Widget& operator=(const Widget& rhs){
            // ...
            *pImpl = *(rhs.pImpl);   // 复制Widget时,令其拷贝其WidgetImpl对象
            // ...
        }
        // 增加公有的swap成员函数
        void swap(Widget& other){
            using std::swap;  // 这个声明很重要!
            swap(pImpl, other.pImpl);
        }
        // ...
    private:
        WidgetImpl* pImpl;
    };

    // 这是std::swap针对T是Widget的特化版本,通过编译。
    namespace std{
        template<>    // 表示它是std::swap的一个特化版本
        void swap (Widget& a, Widget& b){  // swap表示这个特化版本是针对T为Widget设计的
           a.swap(b);  // 交换Widget对象时,只要调用swap成员函数即可
        }
    }
    3.新的问题但是,假设Widget和WidgetImpl都是类模板而不是普通的类呢?两个类模板如下所示:
    template<typename T>
    class WidgetImpl{
        // ...
    };

    template<typename T>
    class Widget{
        // ...
    };
    照葫芦画瓢,在Widget类模板中放入一个公有成员函数swap。不幸的是,仍然像2中的做法那样就不行啦,此时在特化std::swap时会出现乱流。
    namespace std{
        template<typename T>
        void swap>(Widget& a, Widget& b){  // 错误!
            a.swap(b);
        }
    }
    出现乱流的原因在于我们企图部分特化一个函数模板,但C++只允许对类模板进行部分特化,在函数模板上部分特化是不行的解决方法:当你打算对一个函数模板进行部分特化时,需要为它添加一个重载版本。
    namespace std{
        template<typename T>
        void swap(Widget& a, Widget& b){  // std::swap的一个重载版本
            a.swap(b);
        }
    }
    一般来说,重载函数模板是没有问题的。但是,std是一个特别的命名空间。客户可以全部特化std中的模板,但是不可以添加新的类或函数到std中。解决方法声明一个non-member函数swap,让它来调用成员函数swap。但是,不再将那个non-member函数swap声明为std::swap的特化版本或重载版本。如下所示:
    namespace WidgetStuff{
        // 类模板WidgetImpl
        template<typename T>
        class WidgetImpl{
            // ...
        };

        // 类模板Widget
        template<typename T>
        class Widget{
            // ...
            // 内含swap成员函数
        };
        // ...

        template<typename T>
        void swap(Widget& a, Widget& b){   // non-member函数swap,不属于std命名空间
            a.swap(b);
        }
    }
    上面的做法对类和类模板都行得通,似乎我们任何时候都可以使用此方法。不幸的是,如果你想让你的类专属版swap函数在尽可能多的地方被调用,你需要同时在该类所在的命名空间内写一个non-member版本的swap函数和一个std::swap特化版本。4.究竟调用哪个swap函数呢?前面三部分的内容,我们都是从程序编写者的角度去看问题。下面,我们从程序调用者即客户的角度出发,假设你正在写一个函数模板,它的内部需要交换两个对象值。如下所示:
    template<typename T>
    void doSomething(T& obj1, T& obj2){
        // ...
        swap(obj1, obj2);
        // ...
    }
    上面程序段中应该调用哪个swap呢?是默认的swap?还是特化版的std::swap?还是一个可能存在的T专属版本但却放置在某个命名空间内?其实,你的本意是调用T专属版本,并在该版本不存在的情况下调用std::swap。因此,你可以写成如下的代码:
    template<typename T>
    void doSomething(T& obj1, T& obj2){
        using std::swap;  // std::swap在此函数内可用
        // ...
        swap(obj1, obj2);  // T专属版本
        // ...
    }
    其中,需要注意的一点是别在调用的时候额外添加修饰符,因为那会影响C++选择适当的函数。如下面的错误调用方式,只会强迫编译器只认识std命名空间中的swap函数,因此不会再调用一个定义在其他命名空间中的T专属版本swap函数。
    std::swap(obj1, obj2);  // 错误的调用swap方式
    最后注意的地方成员函数版本的swap函数绝不可抛出异常。这是因为默认的swap函数是以拷贝构造函数和赋值运算符重载为基础实现的,而在一般情况下两者都允许抛出异常。因此,当你写了一个定制化版本的swap函数,往往提供的不只是高效交换对象值的方法,而且也并不抛出异常。一般而言,这两个swap特性是连在一起的,因为高效率的swap几乎总是基于对内置类型的操作(如pimpl手法的底层指针),而内置类型上的操作绝不会抛出异常。5.总结(1) 当std::swap对你的类型效率不高时,提供一个swap成员函数,并确保这个函数不抛出异常。(2) 如果你提供一个成员函数版本的swap,也应该提供一个non-member版本的swap用来调用前者。对于类而言,也请使用特化版本的std::swap。(3) 调用swap时应针对std::swap使用using进行声明,然后调用swap并且不带任何命名空间修饰。(4) 为自定义的类而全部特化std模板是没问题的,但千万不要往std中添加任何东西。

    觉得好看,请点这里↓

    展开全文
  • swap函数

    千次阅读 2009-08-11 20:48:00
    今天碰到一个奇怪的问题:#include ...int main(){ void swap(int &,int &); int i=3,j=5; swap(i,j); cout return 0;}void swap(int &a,int &b){int temp; temp=a; a=b; b=temp;} vc6.0下,输出的是:i=3,

    今天碰到一个奇怪的问题:

    #include <iostream>
    using namespace std;
    int main()
    {
     
     void swap(int &,int &);
     int i=3,j=5;
     swap(i,j);
     cout<<"i="<<i<<" "<<"j="<<j<<endl;
     return 0;
    }

    void swap(int &a,int &b)
    {int temp;
     temp=a;
     a=b;
     b=temp;
    }

     

    vc6.0下,输出的是:

    i=3,j=5

     

    交换不了。

    解决方案,

    1.改函数名:

    #include <iostream>
    using namespace std;
    int main()
    {
     
     void swapa(int &,int &);
     int i=3,j=5;
     swapa(i,j);
     cout<<"i="<<i<<" "<<"j="<<j<<endl;
     return 0;
    }

    void swapa(int &a,int &b)
    {int temp;
     temp=a;
     a=b;
     b=temp;
    }

    2.不用标准库,

    #include <iostream.h>
    int main()
    {
     
     void swap(int &,int &);
     int i=3,j=5;
     swap(i,j);
     cout<<"i="<<i<<" "<<"j="<<j<<endl;
     return 0;
    }

    void swap(int &a,int &b)
    {int temp;
     temp=a;
     a=b;
     b=temp;
    }
    3.不用命名空间

    #include <iostream>
    int main()
    {
     
     void swap(int &,int &);
     int i=3,j=5;
     swap(i,j);
     std::cout<<"i="<<i<<" "<<"j="<<j<<std::endl;
     return 0;
    }

    void swap(int &a,int &b)
    {int temp;
     temp=a;
     a=b;
     b=temp;
    }

    4.直接调用:

    #include <iostream>
    using namespace std;
    int main()
    {
     
     int i=3,j=5;
     swap(i,j);
     cout<<"i="<<i<<" "<<"j="<<j<<endl;
     return 0;
    }

    5.去掉函数声明。

    #include<iostream>
    using namespace std;
    void swap(int &a,int &b)
    {
     int temp=a;
     a=b;
     b=temp;
    }


    int main()
    {
     int a=11,b=5;
     swap(a,b);
     cout<<a<<" "<<b<<endl;
     return 0;
    }

     

     

     

    问题:

    出现上面问题,关键是跟c++标准库函数里面的swap函数冲突了。

    就是存在std::swap

    标准库的swap函数,跟上面自定义的swap函数(形参,返回值)一模一样的。因此编译器就出现问题了。

    单步调试的结果是,翻译器跳过上面的 swap(i,j)语句。

    通过单步调试第四个程序,找到std::swap的原型:

     

    template<class _Ty> inline
     void swap(_Ty& _X, _Ty& _Y)
     {_Ty _Tmp = _X;
     _X = _Y, _Y = _Tmp; }

     

    启示:

    不要直接用using namespace std;

    这种方法,要用到的时候,才用std:: 这样。

    例如,std::endl;等等。

    避免出现上面问题。

     

     

     

     

     

     

     

     

     

     

    展开全文
  • swap函数几乎是所有初学者都写过的一个最基本的函数之一,通常是用它来了解函数概念、形参与实参、引用和指针。然而,这个极为基础的函数却有着非常重要的作用。正因为它的重要性、普遍性,意味着swap函数必须有着极...
  • C++中的swap函数

    万次阅读 多人点赞 2019-08-10 09:23:32
    C++中的swap函数:交换函数 好处:不用担心交换变量精度的缺失,无需构造临时变量,不会增加空间复杂度 swap 包含在命名空间std 里面 swap(a,b);(交换两个数) swap(a[i] = b[j]);(交换两个位置上的变量) ....
  • python中实现swap函数

    2021-02-26 13:57:03
    python中实现swap函数python中实现swap函数python中实现swap函数 Python以引用方式管理对象,你可以交换引用,但通常不能交换内存中的对象值。 def swap(t1, t2): return t2, t1 在Python中交换a,b,不需要交换...
  • 花样swap函数

    2015-05-11 07:16:20
    常见的几种swap函数的写法及简单分析 泛型法的swap函数
  • c语言中swap函数_C ++中的swap()函数

    千次阅读 2020-07-19 03:04:52
    c语言中swap函数 介绍 (Introduction) In this tutorial, we are going to learn the swap() function in C++ programming language. Swapping is a simple operation in C++ which basically is the exchange of ...
  • C++ 容器swap函数

    2019-12-07 17:38:27
    1、swap函数交换俩个相同类型容器的内容,交换俩个容器的速度非常快,因为只交换容器的数据结构,而不交换元素值;但是如果是array调用swap函数,速度将会很慢,因为他是交换的元素值,交换速度与array大小成正比; ...
  • 钒铅矿C.84: A swap function may not failC.84:swap函数不应该失败Reason(原因)swap is widely used in ways that are assumed never to fail and programs cannot easily be written to work correctly in the ...
  • 温故而知新:C语言中swap函数

    万次阅读 多人点赞 2014-10-17 13:46:13
    最近在学习数据结构和算法,发现使用到swap()函数,于是重新看了一下swap函数的各种实现,发现我对函数实参和形参理解不够透彻,现在分享我对swap的一些见解。 我们通常使用以下一段代码来实现整型变量的交换: ...
  • swap函数自定义实现

    2019-02-24 13:46:01
    swap函数大家都很熟悉了,用于将两个对象进行交换,但是在std中swap需要进行一个拷贝构造,两次赋值操作。这对于小对象是可以接受的,但对于较大的对象来书,这个时间可是有点长了,所以可能要在特定的类中自定义...
  • c语言中的Swap函数

    2020-10-11 23:25:20
    在学习C语言时,我们学到指针这里的时候,使用到Swap()函数,下面是关于Swap函数的一些见解。 首先我们通常会用下面的代码来实现Swap函数整型变量的交换: void Swap(int *p1,int *p2) { int tmp; tmp = *p1; *...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,610
精华内容 2,644
关键字:

swap函数