2013-08-15 38 views
5

tôi tò mò về những gì xảy ra với đoạn mã này trong Delphi 2010:phụ UnicodeString để WideString trong Delphi

function foo: WideString; 
var 
    myUnicodeString: UnicodeString; 
begin 
    for i:=1 to 1000 do 
    begin 
    myUnicodeString := ... something ...; 

    result := result + myUnicodeString; // This is where I'm interested 
    end; 
end; 

Có bao nhiêu chuỗi chuyển đổi có liên quan, và bất kỳ đặc biệt xấu hiệu suất-khôn ngoan?

Tôi biết chức năng này chỉ cần trả về một thay vì UnicodeString, nhưng tôi đã thấy mẫu chống này trong mã phát trực tiếp VCL và muốn hiểu quy trình.

+0

Bạn có cố gắng tìm kiếm điều đó trong cửa sổ CPU của trình gỡ lỗi không? – OnTheFly

+0

@OnTheFly: Nó thực sự là một phần của một dự án C++ Builder, và vì một số lý do BCB2010 không thích thiết lập các điểm ngắt trong mã VCL ... Tôi sẽ cố gắng bước qua một số chi tiết. – Roddy

+0

Nếu bạn không có Delphi để nghiên cứu mã được tạo cho tescase của bạn, tôi có thể đăng một disassembly, nhưng tôi thực sự không chắc chắn làm thế nào để trình bày nó ở dạng hữu ích ... – OnTheFly

Trả lời

8

Để trả lời câu hỏi của bạn về những gì đang thực sự làm, tuyên bố này:

result := result + myUnicodeString; 

Liệu sau:

  1. cuộc gọi System._UStrFromWStr() để chuyển đổi Result đến một temp UnicodeString

  2. gọi System._UStrCat() để nối myUnicodeString lên t emp

  3. gọi System._WStrFromUStr() để chuyển đổi nhiệt độ thành WideString và gán lại cho Result.

Có một chức năng System._WStrCat() cho concatenating một WideString lên một WideString (và System._UStrCat() cho UnicodeString). Nếu CodeGear/Embarcadero thông minh hơn, họ có thể đã thực hiện quá tải System._WStrCat() mất UnicodeString làm đầu vào và WideString làm đầu ra (và ngược lại để nối một số WideString lên UnicodeString). Bằng cách đó, không cần phải chuyển đổi UnicodeString tạm thời nữa. Cả hai WideStringUnicodeString được mã hóa dưới dạng UTF-16 (chủ yếu, nhưng tôi sẽ không tham gia ở đây), vì vậy ghép chúng lại với nhau chỉ là vấn đề phân bổ và di chuyển, giống như khi ghép hai số UnicodeString s hoặc hai WideString s với nhau.

+0

Cảm ơn Remy. Điều đó giải thích rất nhiều! – Roddy

+0

+1 cho phân tích mà tôi không thể cung cấp –

4

Hiệu suất kém. Không cần bất kỳ chuyển đổi mã hóa nào vì mọi thứ đều được mã hóa UTF-16. Tuy nhiên, WideString là một trình bao bọc xung quanh loại COM BSTR hoạt động kém hơn so với UnicodeString gốc.

Đương nhiên, bạn nên làm tất cả công việc của mình với các kiểu gốc, hoặc là UnicodeString hoặc TStringBuilder và chuyển đổi thành WideString tại thời điểm cuối cùng có thể.

Đó thường là một chính sách tốt. Bạn không muốn sử dụng WideString nội bộ vì nó hoàn toàn là một loại interop. Vì vậy, chỉ chuyển đổi thành (và từ) WideString tại ranh giới interop.

+0

Cảm ơn.Tôi đặc biệt tò mò về việc liệu chuỗi concat (rộng: = rộng + uni) xảy ra trong unicode hoặc tên miền rộng. Nếu đó là unicode, thì hai chuyển đổi có liên quan. (wide-> uni, concat, uni-> wide) – Roddy

+0

Tôi không biết chi tiết cụ thể nào trên đầu của tôi. Nhưng thật dễ dàng để làm việc với một trình gỡ rối. Một cái gì đó tôi không có ngay bây giờ. Dù bằng cách nào, bạn không muốn nó. Làm tất cả công việc của bạn với TStringBuilder và chuyển đổi sang WideString càng muộn càng tốt. Tất cả các kết nối đó sẽ là xấu ngay cả với các chuỗi thuần túy thuần túy. Nặng trên đống. –

+0

Nó không thực sự là mã của tôi. It's trong classes.pas trong D2010 (CombineWideString). Tôi đã có một vấn đề mà một hình thức với một tài sản chuỗi 4MB duy nhất (có, nhưng có một lý do tốt!) Mất 2,5 phút (!) Để tải khi sử dụng văn bản DFMs, và dưới một giây với nhị phân. – Roddy