سؤال

أحاول استخدامها std::string بدلاً من char* كلما كان ذلك ممكنًا، ولكنني أشعر بالقلق من أن الأداء قد يؤدي إلى انخفاض كبير جدًا.هل هذه طريقة جيدة لإرجاع السلاسل (لا يوجد خطأ في التحقق من الإيجاز)؟

std::string linux_settings_provider::get_home_folder() {
    return std::string(getenv("HOME"));
}

سؤال ذو صلة أيضًا:عند قبول السلاسل كمعلمات، هل يجب أن أستقبلها كـ const std::string& أو const char*?

شكرًا.

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

المحلول

والعودة السلسلة.

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

واستغرق الأمر سنوات عديدة للحصول على التجريد سلسلة جيد في C ++. لا أعتقد أن بيارني Stroustroup، حتى الشهيرة لله المحافظ "تدفع الا لما كنت تستخدم" القول المأثور، من شأنه أن يسمح القاتل أداء واضحة في اللغة. التجريد العالي جيدة.

و

نصائح أخرى

وإرجاع سلسلة، مثل الجميع يقول.

<ط> عند قبول سلاسل كمعلمات، يجب أن تحصل عليها كما const std::string& أو const char*؟

وانا اقول اتخاذ أية معلمات CONST بالرجوع، إلا إذا إما أنها خفيفة الوزن بما يكفي لاتخاذ من حيث القيمة، أو في الحالات النادرة التي تحتاج إلى مؤشر فارغة لتكون مدخلا صحيحا بمعنى "لا شيء مما سبق". هذه السياسة ليست محددة لسلاسل.

وغير CONST المعلمات المرجعية هي قابلة للنقاش، لأن من رمز الدعوة (بدون IDE جيد)، لا يمكنك أن ترى على الفور ما اذا انهم تمريرها حسب القيمة أو بالإشارة، والفرق هو المهم. لذلك قد يكون رمز واضح. لبارامس CONST، وهذا لا ينطبق. الناس في قراءة رمز الدعوة يمكن عادة مجرد افتراض أنه ليس مشكلتهم، ولذلك سوف تحتاج فقط من حين لآخر للتحقق من التوقيع.

في حالة ما إذا كنت تريد الذهاب لأخذ نسخة من ذي الحجة في وظيفة، وينبغي أن تكون السياسة العامة لاتخاذ حجة من حيث القيمة. ثم كان لديك بالفعل نسخة يمكنك استخدامها، وإذا كنت قد نسخها إلى بعض مكان معين (مثل عضو بيانات) ثم يمكنك تحريكه (في C ++ 11) أو المبادلة (في C ++ 03) ل تحصل عليه هناك. وهذا يعطي المترجم أفضل فرصة لتحسين الحالات التي يمر المتصل كائن مؤقت.

لstring على وجه الخصوص، وهذا يشمل الحالة التي يكون فيها يأخذ وظيفة الخاص بك std::string من حيث القيمة، ويحدد الطالب كوسيلة للتعبير حجة سلسلة الحرفي أو char* مشيرا إلى سلسلة منتهية NUL. إذا كنت أخذت const std::string& ونسخها في وظيفة، من شأنه أن يؤدي إلى بناء سلسلتين.

تختلف تكلفة نسخ السلاسل حسب القيمة بناءً على تطبيق STL الذي تعمل معه:

  • تستخدم std::string ضمن MSVC تحسين السلسلة القصيرة، بحيث لا تتطلب السلاسل القصيرة (< 16 حرفًا iirc) أي تخصيص للذاكرة (يتم تخزينها داخل std::string نفسها)، بينما تتطلب السلاسل الأطول تخصيص كومة الذاكرة المؤقتة. في كل مرة يتم نسخ السلسلة.

  • يستخدم std::string ضمن مجلس التعاون الخليجي تطبيقًا معدودًا مرجعيًا:عند إنشاء std::string من char*، يتم تخصيص الكومة في كل مرة، ولكن عند المرور بقيمة إلى دالة، يتم ببساطة زيادة عدد المرجع، مما يؤدي إلى تجنب تخصيص الذاكرة.

بشكل عام، من الأفضل أن تنسى ما سبق وتعيد std::strings حسب القيمة، إلا إذا كنت تفعل ذلك آلاف المرات في الثانية.

يكرر:عند تمرير المعلمة، ضع في اعتبارك أن هناك تكلفة للانتقال من char*->std::string، ولكن ليس من الانتقال من std::string->char*.بشكل عام، هذا يعني أنه من الأفضل قبول مرجع ثابت إلى سلسلة std::string.ومع ذلك، فإن أفضل مبرر لقبول const std::string& كوسيطة هو أنه لا يلزم أن يكون لدى المستدعى رمزًا إضافيًا للتحقق مقابل التحقق.باطل.

ويبدو أن فكرة جيدة.

وإذا لم يكن هذا جزء من البرنامج الحقيقي (مثل لعبة) ولكن تطبيق العادية، ويجب أن تكون أكثر من الغرامة.

وتذكر، " الأمثل من السابق لأوانه هو أصل كل الشرور "

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

في قضيتك قيمة إرجاع الأمثل سيعقد الأمراض المنقولة جنسيا حتى :: لن يتم نسخ السلسلة.

وحذار عند عبور الحدود حدة.

وبعد ذلك فمن الأفضل أن يعود أنواع بدائية منذ أنواع C ++ ليست بالضرورة ثنائي متوافقة عبر إصدارات مختلفة حتى من نفس المجمع.

وأنا أتفق مع غيرها من الملصقات، التي يجب استخدام السلسلة.

ولكن اعلم أن هذا يتوقف على كيفية بقوة يحسن المترجم الخاص بك المؤقتة المتقبلة، وربما لديك بعض الحمل الزائد (أكثر باستخدام مجموعة ديناميكية من حرف). (ملاحظة: والخبر السار هو أنه في 0A C ++، فإن الاستخدام الحكيم للمراجع rvalue لا يتطلب تحسينات مترجم لشراء الكفاءة هنا - وسوف المبرمجين تكون قادرة على تقديم بعض الضمانات الأداء إضافية حول التعليمات البرمجية الخاصة بهم دون الاعتماد على نوعية المترجم).

في الوضع الخاص بك، هو الحمل الزائد يستحق إدخال إدارة الذاكرة اليدوي؟ فإن معظم المبرمجين معقول نختلف - ولكن إذا كان التطبيق الخاص بك لا ينتهي وجود مشكلات في الأداء، فإن الخطوة المقبلة ستكون للصفحة الشخصية طلبك - وبالتالي، إذا كنت تفعل إدخال التعقيد، يمكنك أن تفعل ذلك مرة واحدة فقط لديك دليل جيد على أن هناك حاجة لتحسين الكفاءة الكلية.

وذكر أحدهم أن قيمة إرجاع الأمثل (RVO) هو غير ذي صلة هنا - أنا أختلف

.

والنص القياسي (C ++ 03) على هذا يقرأ (12.2):

[بيغن اقتباس قياسي]

<اقتباس فقرة>   يتم إنشاء

والمؤقتات من نوع فئة في سياقات مختلفة: ملزمة لrvalue إلى مرجع (8.5.3)، والعودة إلى rvalue (6.6.3)، وهو التحويل الذي يخلق rvalue (4.1، 5.2.9، 5.2.11 ، 5.4)، ورمي استثناء (15.1)، ودخول معالج (15.3)، وفي بعض التهيئة (8.5). [ملاحظة: يتم وصف مدى الحياة للكائنات استثناء في 15.1. ] وحتى عندما يتم تجنب إنشاء كائن مؤقت (12.8)، كل الدلالي   يجب احترام القيود كما لو تم إنشاء كائن مؤقت. [مثال: حتى لو لم يتم استدعاء منشئ نسخة، كل القيود الدلالي، مثل إمكانية الوصول (البند 11)، يجب أن يكون راضيا. ]

 [Example:  
struct X {
  X(int);
  X(const X&);
  ˜X();
};

X f(X);

void g()
{
  X a(1);
  X b = f(X(2));
  a = f(a);
}
<اقتباس فقرة>   

وهنا، التنفيذ قد تستخدم مؤقت فيه لبناء X (2) قبل أن يمررها إلى f () باستخدام نسخ منشئ X؛ و بدلا من ذلك، X (2) قد شيدت في المساحة المستخدمة لعقد الحجة. أيضا، يمكن أن تستخدم مؤقت لعقد نتيجة لو (X (2)) قبل نسخها إلى b باستخدام copyconstructor X؛ و بدلا من ذلك، قد يتم بناؤها و (الصورة) النتيجة في ب. من ناحية أخرى، فإن التعبير و= و (أ) يتطلب مؤقتة إما حجة أو نتيجة لو (أ) لتجنب التعرجات غير مرغوب فيه   أ. ]

[نهاية قياسي اقتباس]

وأساسا، النص أعلاه يقول أنه يمكنك أن تعتمد على RVO في حالات التهيئة، ولكن ليس في حالات الاحالة. والسبب هو، عند تهيئة كائن، لا توجد وسيلة أن ما كنت تهيئة مع يمكن أبدا أن مستعارة إلى الكائن نفسه (والذي هو السبب في أنك لم تفعل الاختيار الذاتي في منشئ نسخة)، ولكن عندما تفعل واجب، ما في وسعها.

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

وأنا أتفق مع duffymo. يجب عليك تقديم طلب العمل مفهومة أولا ثم، إذا كان هناك حاجة، هجوم الأمثل. وهو في هذه النقطة التي سيكون لديك فكرة عن المكان الذي هي العقبات الرئيسية، وسوف تكون قادرة على إدارة أكثر كفاءة وقتك في جعل التطبيق أسرع.

وأنا أتفق معduffymo.لا تقم بالتحسين حتى تقوم بالقياس، فهذا ينطبق بشكل مضاعف عند إجراء التحسينات الدقيقة.و دائما:يقيس قبل و بعد لقد قمت بالتحسين، لمعرفة ما إذا كنت قد غيرت الأمور بالفعل إلى الأفضل.

وإرجاع سلسلة، فإنه ليس كبيرا من خسارة من حيث الأداء ولكن بالتأكيد سيخفف عملك بعد ذلك.

وبالإضافة إلى ذلك، يمكنك دائما مضمنة في وظيفة ولكن معظم محسن اصلاحها على أي حال.

إذا قمت بتمرير سلسلة المشار إليها والتي تعمل على هذه السلسلة لا تحتاج للعودة أي شيء. ؛)

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