从“集合”实例分析修饰函数返回值的const作用

从“集合”实例分析修饰函数返回值的const作用
        这段时间在复习C++基础,算法与数据结构,以及学习STL。所以,SDL的教程更新会慢些。因为我还是以自己的项目为核心进行学习的,所以基础知识和游戏设计涉及到图形,控制和多线程的内容学习,应该是会有些交叉的。
        发现这个问题,是因为一直以来思考的一个算法——关于“集合”的实现。这个集合就是数学中的集合,与计算机中数列一个最大的不同在于,集合的元素是互异的。因为这两天在熟悉vector,所以觉得用vector实现集合再合适不过了。STL确实是很好很强大的体系,无论是内存管理,还是链表的实现,让我们可以省很多心。其实关于为什么要实现集合,也是因为我在计划实现类似英雄无敌战场计算移动的一系列算法中,很多地方会用到集合的概念,甚至包括并集和差集等等。也许我想到的算法是很笨拙的,但是在我还没有完全阅读相关的已有代码之前,觉得完全凭自己的认识,实现这些算法还是很有意义的,所以,从学习C++的第一天开始,我就在试图找到解决这些问题的方法,而现在,越来越清晰了,呵呵。
        我的思路很直接也很简单,就是把一个数组中的元素往一个新的数组中填,新填充的元素会遍历新数组中已有的元素,如果与之互异,则填入(push),否则就跳到下一个。以上就已经确立了成员数据(私有)和构造函数。因为我们需要“集合化”了的数组是可以被外部访问的,所以一个最简单的方法就是把成员数据公有——这确实是很简单,而且这样就不会出现今天我们要讨论的问题了;另外一个笨办法是用一个公有方法,返回成员数据的值——我就是这么做的,因为这貌似更符合OOP的“数据隐藏”的精神-_-!!!。很快可以写出头文件:
#ifndef AGGREGATE_H_
#define  AGGREGATE_H_

#include 
< iostream >
#include 
< vector >
#include 
< algorithm >

class  Aggregate
{
private :
    std::vector
< int >  agg;
public :
    Aggregate(std::vector
< int >&  temp);
    
const  std::vector < int >  getAgg()  const ;
};

#endif
请注意那个红色的const,其实我想说的是,第一次写这个程序的时候,我并没有这个const。一直以来,除了在重载“=”的时候我大概清楚修饰返回值const的作用是可以避免让返回值做左值,其他时候还真不太明白这个const的作用,只是本着C++的精神——能const就const吧-_-!!!。实现文件:
#include  " aggregate.h "

Aggregate::Aggregate(std::vector
< int >&  temp)
{
    
for  ( std::vector < int > ::iterator pTemp  =  temp.begin(); pTemp  !=  temp.end(); pTemp ++  ) {
        
bool  findSame  =   false ;
        
for  ( std::vector < int > ::iterator pAgg  =  agg.begin(); pAgg  !=  agg.end(); pAgg ++  )
            
if  (  * pTemp  ==   * pAgg )
                findSame 
=   true ;
        
if  ( findSame  ==   false  )
            agg.push_back(
* pTemp);
    }
}

const  std::vector < int >  Aggregate::getAgg()  const
{
    
return  agg;
}
一切都很完美,不是吗?顺手就继续写出一个测试用的程序:
# include "aggregate.h"

void show( int& i);

int main( int argc,  char* argv[])
{
    std::vector< int> tempArray;
     int temp;
     bool goon =  true;

     while ( goon ==  true ) {
        std::cout << "#" << tempArray.size()+1 << "= ";
        std::cin >> temp;
         if ( temp == -1 ) {
            goon =  false;
             continue;
        }
        tempArray.push_back(temp);
    }

    std::cout << "You've entered " << tempArray.size() << " numbers." << std::endl;

    for_each(tempArray.begin(), tempArray.end(), show);

    std::cout << "----------------------------\n" << "Now, to be aggregate\n";

    Aggregate tempAgg (tempArray);
    std::cout << "There are " << tempAgg.getAgg().size() << " different numbers.\n";
    for_each(tempAgg.getAgg().begin(), tempAgg.getAgg().end(), show);


     return 0;
}

void show( int& i)
{
    std::cout << i << std::endl;
}
很不幸,编译正常的通过了(注意,没有红色的const的时候)。
但是,运行时出现了错误。
运行时错误是件令人很郁闷的事情,因为这意味着编译器不会帮你找到出错的地方。
幸运的是,直觉让我觉得类似tempAgg.getAgg().begin()的用法有问题,所以,我改成了:(紫色那部分代码)
    std::cout  <<   " ----------------------------\n "   <<   " Now, to be aggregate\n " ;

    Aggregate tempAgg (tempArray);
    std::vector
< int >  tempAggArray  =  tempAgg.getAgg();
    std::cout 
<<   " There are  "   <<  tempAggArray.size()  <<   "  different numbers.\n " ;
    for_each(tempAggArray.begin(), tempAggArray.end(), show);
这样,问题是解决了。但是我们回头分析一下,刚才的问题到底出在什么地方呢?
其实,如果我们加上红色的const,使用原来的代码进行编译的时候,编译器是可以指出我们的错误的,确实是tempAgg.getAgg().begin()的用法出了问题。具体的原因包含在<algorithm>里面,我没有仔细去分析,但是我们至少明白了,方法begin()会试图修改其对象的返回值!
        让错误被发现在编译阶段,远远好于被发现在运行时阶段。我想,这就是C++中const最大的作用。所以,总结起来还是C++的一句话,能const,就const吧。:)

你可能感兴趣的:(从“集合”实例分析修饰函数返回值的const作用)