==【注意】==
程序语言只是我们与计算机交流并让计算机实现我们创造性思想的工具,可以并鼓励深入掌握一门语言,但千万别沉迷于钻某种语言的牛角尖,一定要把握好二者间的度

本帖属不定时连载贴,以试卷的形式提出一个比较基础的问题供大家思考讨论,问题的解析将在下一更新贴中一并给出,这样做是希望还不清楚问题的朋友有自己思考和讨论的时间,希望大家能从这些帖子中有所收获。

贴中问题属我在学习C\C++过程中遇到的一些语法或者比较隐晦的程序问题,其中有自己的总结,也不乏网络上搜索到的经典解析,在此分享给大家,希望能起到抛砖引玉的作用

我已认真检查过自己的帖子,但难免有疏忽,如大家在阅读过程中仍发现有问题,请及时通知,我会及时更正,以免误导大家,万分感谢^_^


【No.16 异常的直接插入排序】

由于连载形式,每帖第二部分都配有上一问题的解答。为了保持帖子的针对性和一致性,此贴仅供交流讨论本次问题若大家对上一问题有任何疑问,请通过解答末尾的传送链接前往该问题贴回复讨论



[问题No.16]
下面的直接插入排序逻辑没有问题,但为什么无法正确运行呢?

复制内容到剪贴板
代码:
void insertSort(int *arr, const size_t arrLength){
  for(size_t i=1; i<arrLength; ++i){
    int elemToInsert = arr;
    size_t j = 0;
    for(j=i-1; j>=0; --j){
      if(arr[j] > elemToInsert)
        arr[j+1] = arr[j];
      else
        break;
    }
    arr[j+1] = elemToInsert;
  }
}

No.15 看似完美的operator=


本主题主要是向大家提出对象“自赋值”的问题,以引起大家的重视。这是个经典的问题,我们在编写赋值操作符时,既要具有自赋值安全性(即自赋值不应该改变原对象的状态),也应该具有异常安全性。下面的代码对这一问题进行了简要阐释,希望尚不知道的午饭引起重视。

复制内容到剪贴板
代码:
#include<iostream>
#include<string>

using std::cout;
using std::endl;
using std::string;

#define WITHOUT_IDENTITY_TEST  //没有对自赋值做检测
//#define IDENTITY_TEST  //有自赋值检测,但没有异常安全
//#define SAVING_ORIGIN_POINTER  //提供异常安全,并顺带提供了自赋值检测
//#define COPY_AND_SWAP  //一种被称为copy and swap的技术提供异常安全,并顺带提供自赋值检测

class Foo
{
  public:
    Foo(const string str) : _str(new string(str)){ }
    Foo(const Foo &foo){ _str = new string(*foo._str); }
    ~Foo(void){ delete _str; }

#ifdef WITHOUT_IDENTITY_TEST
    //没有对自赋值做检测
    Foo& operator =(const Foo &foo){
      delete _str;
      _str = new string(*foo._str);
      return *this;
    }
#endif

#ifdef IDENTITY_TEST
    //有自赋值检测,但没有异常安全
    Foo& operator =(const Foo &foo){
      if(this == &foo)
        return *this;
      delete _str;
      _str = new string(*foo._str);
      return *this;
    }
#endif

#ifdef SAVING_ORIGIN_POINTER
    //提供异常安全,并顺带提供了自赋值检测
    Foo& operator =(const Foo &foo){
      string *original = _str;
      _str = new string(*foo._str);
      return *this;
    }
#endif

#ifdef COPY_AND_SWAP
    //一种被称为copy and swap的技术提供异常安全,并顺带提供自赋值检测
    Foo& operator =(const Foo &foo){
      Foo temp(foo);
      _swap(temp);
      return *this;
    }
#endif

    const string& getStr(void) const { return *_str; }

  private:
    void _swap(Foo &foo){
      string temp = *_str;
      *_str = *foo._str;
      *foo._str = temp;
    }
    string *_str;
};

int main(int argc, char **argv)
{
  Foo f1("first"), f2("second");
  cout<<"f1 = "<<f1.getStr()<<"\tf2 = "<<f2.getStr()<<endl;

  f1 = f2;
  cout<<"f1 = "<<f1.getStr()<<"\tf2 = "<<f2.getStr()<<endl;

  f1 = f1;
  cout<<"f1 = "<<f1.getStr()<<"\tf2 = "<<f2.getStr()<<endl;

  return EXIT_SUCCESS;
}