一. PChar注意用例

    

1.1 小心PChar转化

    

    大家看下面这个函数,会得到预期的结果,答案是也许偶尔你会得到你要的结果。但是,这样用是错误的!

    

    function title(n: Integer): PChar;
        var
        s: string;
        begin
        s := Format('title - %d', [n]);
        Result := PChar(s);
        end;   

    

    因为在该函数调用结束后,String已经释放了。也许你要问,我试过了啊可以得到正确的结果啊!     所以上面说偶尔你会得到你要的结果,是因为string的引用

    

    计数已经为0了,即内存标记为该string的区域是空闲的;但并没有对该区域进行初始化,所以如果以后的程序没用过该内存区域的话;你就侥幸得到了正确的返回

    

值!

    

1.2 PChar的分配空间

    

1.2.1     由于这样的例子很多,我在这里就举一个在类中运用PChar的例子:

    

    TBidCell = class
        private
          FName: PChar;
    
          procedure SetName(const Value: string);
          function GetName: string;
        public
          constructor Create; reintroduce;
          destructor Destroy; override;
    
          property Name: string read GetName write SetName;
        end;

    

    由于私有变量FName是一个PChar类型,所以必须给它分配空间;我想大家已经想到了,要在SetName方法里分配合适的空间,就如:

    

constructor TBidCell.Create;
    begin
    GetMem(FName, 0);              // 这里需要注意的是对     分配内存和释放内存 一定要成对的出现
    end;
    
    destructor TBidCell.Destroy;
    begin
    FreeMem(FName);
    inherited;
    end;
    
    function TBidCell.GetName: string;
    begin
    Result := FName;
    end;
    
    procedure TBidCell.SetName(const Value: string);
    begin
    if FName = Value then Exit;
    
    FreeMem(FName);
    GetMem(FName, Sizeof(Value));

    StrCopy(FName, PChar(Value));
    end;

    

1.2.2     又如下一段代码:

    

1.2.2.1     例子:

    

    TBidCell = class
        private
          FName: PChar;
        public
          constructor Create; reintroduce;
          destructor Destroy; override;
    
          property Name: string read GetName write SetName;
        end;

    

    constructor TBidCell.Create;
        begin
        end;
    
        destructor TBidCell.Destroy;
        begin
        FreeMem(FName);
        inherited;
        end;

    

        当程序调用TBidCell.Create后,再直接调用Free;程序是不会报错的,因为类创建时已经将所有变量初始化了;所以再Destroy中调用FreeMem(FName)而不会

    

出错。但是,推荐 分配和释放内存 要成对出现。

    

1.2.2.2     又如例子

    

    procedure TForm1.Button1Click(Sender: TObject);
        var
            s: PChar;
        begin
    
            FreeMem(s);
        end;

    

    这段代码在Debug编译环境运行下,是不会报任何错误的;但是,当编译前选择优化编译时,就会释放报错!!

    

二. PChar、String、ShortString、AnsiString、WideString的区别

    

2.1 shortstring:

    

    与传统的Pascal字符串相对应,存储格式为压缩格式,字符个数有限,最大
    为255个

    

2.2 ansistring(string缺省编译状态下):

    

    存储格式为压缩格式,一个字符串的个数和大(最大长度可以到2GB)。字符串中的字符也基于标准的ANSIChar字符类型WideString:与AnsiString类似,不

    

过是基于WideChar字符类型(UniCode字符集),用了存储Unicode字符。引入这种类型,主要是为了支持OLE编程

    

2.3 至于string和PChar的区别就多了

    


            string和Char数组都是一块内存, 其中存放连续的字符. string保存具体字符的内存对用户是透明的, 由Delphi管理它的分配, 复制和释放, 用户不能干预

    

(其实也可以, 不过是通过非法途径). Char数组就不必说了吧?

    

    PChar是一个指针, 它的大小只有32位. 定义时由Delphi自动填0. 要将PChar作为字符串使用的话必须自己分配内存用完必须自己释放. PChar型字符串由#0表

    

示字符串结尾Delphi所提供的相关PChar字符串的操作都是判断#0来决定字符串的结尾的。因为PChar是指针,所以它能指向任何地方(也就是说它不一定非要指向字

    

符串不可).把一个String赋值给PChar只是将String中保存具体字符串的内存的地址给PChar变量. 当然也可以把Char数组第一个元素的地址给PChar.至于 哪个占

    

用内存小, Char数组<PChar(指分配过字符串的)<string(除了具体字符串外还 包含字符串长度)如果空字符串那么PChar<String<array [0..n] of Char
     

    

从速度来说毫无疑问string最慢, 例如:作为参数传递(非var调用时)给过程时string将整个字串的副本传递过去, PChar将指针本身的副本传递过去(32位), Char

    

    数组和PChar一样, 传递的是第一个元素的地址副本.不过就灵活性来说string最高, 而且Delphi支持的函数最多. 另外可以将String作为Buffer使用(因为它当中

    

可以包含字符0).

    

 

posted on 2006-11-16 19:21  望天  阅读(2885)  评论(0编辑  收藏  举报