سؤال

متى يجب أن أستخدم std::string ومتى يجب أن أستخدمه char* لإدارة المصفوفات charق في C++؟

يبدو أنك يجب أن تستخدم char* إذا كان الأداء (السرعة) أمرًا بالغ الأهمية وكنت على استعداد لقبول بعض الأعمال المحفوفة بالمخاطر بسبب إدارة الذاكرة.

هل هناك سيناريوهات أخرى يجب وضعها في الاعتبار؟

هل كانت مفيدة؟

المحلول

ويمكنك تمرير الأمراض المنقولة جنسيا :: سلاسل بالرجوع إذا كانت كبيرة لتجنب النسخ، أو مؤشر إلى مثيل، لذلك لا أرى أي ميزة حقيقية باستخدام مؤشرات شار.

وأنا استخدم الأمراض المنقولة جنسيا :: سلسلة / wstring لكل شيء أكثر أو أقل وهذا هو النص الفعلي. char * هو مفيد لأنواع أخرى من البيانات على الرغم من ويمكنك أن تكون متأكدا من أنه يحصل يتم deallocated كما ينبغي. إلا STD :: ناقلات هو الطريق للذهاب.

وربما يكون هناك استثناءات لهذا كله.

نصائح أخرى

وجهة نظري هي:

  • لا تستخدم أبدًا char * إذا لم تستدعي الرمز "C".
  • استخدم دائمًا std::string:إنه أسهل، وأكثر ودية، وهو محسّن، وهو قياسي، وسوف يمنعك من وجود أخطاء، وقد تم فحصه وثبت نجاحه.

استخدام سلسلة الخام

نعم، وأحيانا كنت حقا يمكن القيام بذلك. عند استخدام CONST شار *، صفائف شار المخصصة على المكدس وسلسلة حرفية يمكنك أن تفعل ذلك في مثل هذه الطريقة ليست هناك تخصيص الذاكرة على الإطلاق.

والكتابة هذه المدونة يتطلب في كثير من الأحيان مزيد من التفكير والرعاية من استخدام سلسلة أو ناقلات، ولكن مع التقنيات المناسبة يمكن القيام به. مع التقنيات المناسبة رمز يمكن أن تكون آمنة، ولكن عليك دائما للتأكد من عند نسخ إلى شار [] لديك إما بعض الضمانات على طول السلسلة التي يتم نسخها، أو على فحص ومعالجة السلاسل الضخمة بأمان. عدم القيام بذلك هو ما أعطى عائلة strcpy من وظائف سمعة كونها غير آمنة.

كيف يمكن أن تساعد قوالب الكتابة مخازن شار آمنة

وأما بالنسبة لسلامة شار [] مخازن، يمكن أن تساعد في قوالب، لأنها يمكن أن تخلق التغليف للتعامل مع حجم المخزن المؤقت بالنسبة لك. يتم تنفيذ القوالب مثل هذا على سبيل المثال بواسطة Microsoft لتوفير بدائل آمنة للstrcpy. على سبيل المثال هنا يستخرج من قانون بلدي، رمز حقيقي لديه الكثير من الطرق، ولكن هذا ينبغي أن يكون كافيا للتعبير عن الفكرة الأساسية:

template <int Size>
class BString
{
  char _data[Size];

  public:
  BString()
  {
    _data[0]=0;
    // note: last character will always stay zero
    // if not, overflow occurred
    // all constructors should contain last element initialization
    // so that it can be verified during destruction
    _data[Size-1]=0;
  }
  const BString &operator = (const char *src)
  {
    strncpy(_data,src,Size-1);
    return *this;
  }

  operator const char *() const {return _data;}
};

//! overloads that make conversion of C code easier 
template <int Size>
inline const BString<Size> & strcpy(BString<Size> &dst, const char *src)
{
  return dst = src;
}

مناسبة واحدة يجب عليك استخدامها char* و لا std::string هو عندما تحتاج إلى ثوابت سلسلة ثابتة.والسبب في ذلك هو أنه ليس لديك أي تحكم في وحدات الترتيب التي تقوم بتهيئة متغيراتها الثابتة، وقد يشير كائن عمومي آخر من وحدة نمطية مختلفة إلى السلسلة الخاصة بك قبل تهيئتها. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables

std::string الايجابيات:

  • يدير الذاكرة نيابةً عنك (يمكن أن تنمو السلسلة، وسيقوم التنفيذ بتخصيص مخزن مؤقت أكبر لك)
  • واجهة البرمجة ذات المستوى الأعلى ، تعمل بشكل جيد مع بقية STL.

std::string سلبيات:- لا يمكن لمثيلين مختلفين من سلسلة STL مشاركة نفس المخزن المؤقت الأساسي.لذا، إذا مررت بالقيمة، فستحصل دائمًا على نسخة جديدة.- هناك بعض العقوبات على الأداء، ولكن أود أن أقول ما لم تكن متطلباتك خاصة فهي لا تذكر.

يجب أن تفكر في استخدام char* في الحالات التالية:

  • سيتم تمرير هذه المجموعة في المعلمة.
  • أنت تعرف مسبقًا الحجم الأقصى لمصفوفتك (تعرف ذلك أو تفرضه).
  • لن تقوم بأي تحويل على هذه المجموعة.

في الواقع، في لغة C++، char* غالبًا ما تستخدم للكلمات الصغيرة الثابتة، كخيارات، واسم ملف، وما إلى ذلك...

متى يتم استخدام c++ std::string:

  • السلاسل، بشكل عام، أكثر أمانًا من char*، عادةً عندما تقوم بأشياء باستخدام char*، عليك التحقق من الأشياء للتأكد من أن الأمور على ما يرام، في فئة السلسلة، كل هذا يتم من أجلك.
  • عادةً عند استخدام char*، سيتعين عليك تحرير الذاكرة التي خصصتها، ولا يتعين عليك القيام بذلك باستخدام السلسلة لأنها ستحرر مخزنها المؤقت الداخلي عند تدميره.
  • تعمل السلاسل بشكل جيد مع سلسلة c++، كما أن عمليات الإدخال والإخراج المنسقة سهلة للغاية.

متى تستخدم شار*

  • يمنحك استخدام char* مزيدًا من التحكم في ما يحدث "خلف" الكواليس، مما يعني أنه يمكنك ضبط الأداء إذا كنت بحاجة إلى ذلك.

والاستخدام (CONST) شار * كمعلمات إذا كنت تكتب مكتبة. تطبيقات الأمراض المنقولة جنسيا :: سلسلة تختلف بين المجمعين مختلفة.

إذا كنت تريد استخدام مكتبات C، سيكون لديك للتعامل مع C-السلاسل. ينطبق الشيء نفسه إذا كنت ترغب في فضح API لC.

ويمكنك توقع معظم العمليات على الأمراض المنقولة جنسيا :: سلسلة (مثل على سبيل المثال find) ليتم كما الأمثل ممكن، حتى انهم من المرجح أن تؤدي على الأقل فضلا عن C نظيره النقي.

وكما انه من الجدير بالذكر أن المكررات الأمراض المنقولة جنسيا :: سلسلة في كثير من الأحيان إلى الخريطة مؤشرات إلى الكامنة صفيف حرف. لذلك فإن أي خوارزمية التي وضع على رأس المكررات هي أساسا مطابقة لنفس الخوارزمية على أعلى شار * من حيث الأداء.

أشياء يمكن احترس هي على سبيل المثال operator[] - معظم تطبيقات STL لا يؤدون حدود التحقق، ويجب أن يترجم هذا إلى نفس العملية على صفيف حرف الأساسية. AFAIK STLPort يمكن أن تؤدي اختياريا حدود التحقق، وعند هذه النقطة هذا المشغل سيكون أبطأ قليلا.

فماذا كسب تستخدمه الأمراض المنقولة جنسيا :: سلسلة؟ أنه يعفي لكم من إدارة الذاكرة يدوي. تغيير حجم مجموعة يصبح أسهل، وكان لديك عادة للتفكير أقل عن تحرير الذاكرة.

إذا كنت قلقا حول الأداء عند تغيير حجم سلسلة، وهناك وظيفة reserve التي قد تجدها مفيدة.

وإذا كنت تستخدم مجموعة من حرف في مثل النص الخ استخدام الأمراض المنقولة جنسيا :: سلسلة أكثر مرونة وأسهل استخداما. إذا كنت تستخدم لشيء آخر مثل تخزين البيانات؟ استخدام المصفوفات (تفضل ناقلات)

وحتى عندما يكون الأداء بد لك أفضل استخدام vector<char> - أنه يتيح تخصيص الذاكرة مقدما (طريقة احتياطي ()) وسوف تساعدك على تجنب تسرب الذاكرة. باستخدام ناقل :: المشغل [] يؤدي إلى النفقات العامة، ولكن يمكنك استخراج دائما عنوان المخزن المؤقت ومؤشر بالضبط مثل إذا كان شار *.

وAFAIK داخليا أكثر STD :: سلسلة تنفذ نسخة على الكتابة، إشارة أحصت دلالات لتجنب النفقات العامة، حتى لو لم يتم تمرير سلاسل حسب المرجع.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top