لماذا لا يعد استخدام الصفوف في لغة C++ أكثر شيوعًا؟

StackOverflow https://stackoverflow.com/questions/855110

  •  21-08-2019
  •  | 
  •  

سؤال

لماذا يبدو أن لا أحد يستخدم الصفوف في C++، سواء تعزيز مكتبة Tuple أو المكتبة القياسية لTR1؟لقد قرأت الكثير من أكواد C++، ونادرًا ما أرى استخدام الصفوف، ولكن غالبًا ما أرى الكثير من الأماكن التي تحل فيها الصفوف العديد من المشكلات (عادةً ما تُرجع قيمًا متعددة من الوظائف).

تتيح لك Tuples القيام بجميع أنواع الأشياء الرائعة مثل هذا:

tie(a,b) = make_tuple(b,a); //swap a and b

وهذا بالتأكيد أفضل من هذا:

temp=a;
a=b;
b=temp;

بالطبع يمكنك دائمًا القيام بذلك:

swap(a,b);

ولكن ماذا لو كنت تريد تدوير ثلاث قيم؟يمكنك القيام بذلك باستخدام الصفوف:

tie(a,b,c) = make_tuple(b,c,a);

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

هل هناك أي عيوب كبيرة في الصفوف التي لا أفكر فيها؟إذا لم يكن الأمر كذلك، لماذا نادرا ما تستخدم؟هل هم أبطأ؟أم أن الناس لم يعتادوا عليهم؟هل من الجيد استخدام الصفوف؟

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

المحلول

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

نصائح أخرى

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

ونتيجة لعدم زيادة، مثال: كم عدد الناس استخدام وظيفة وجدت في <algorithm>

وبعبارة أخرى، فإن العديد من المبرمجين C ++ هي ببساطة C المبرمجين باستخدام مترجمات C ++، وربما std::vector وstd::list. وهذا هو أحد الأسباب التي تجعل استخدام boost::tuple ليس أكثر شيوعا.

وو++ جملة الصفوف (tuple) C يمكن أن يكون أكثر قليلا جدا مطول من معظم الناس يرغبون.

والنظر فيما يلي:

typedef boost::tuple<MyClass1,MyClass2,MyClass3> MyTuple;

وحتى إذا كنت تريد أن تجعل الاستخدام المكثف من المجموعات التي إما أن تحصل typedefs الصفوف (tuple) في كل مكان أو تحصل مزعج أسماء الأنواع طويلة في كل مكان. أنا أحب الصفوف. I استخدامها عند الضرورة. لكنها عادة ما تقتصر على بضع حالات، مثل مؤشر N-عنصر أو عند استخدام multimaps لربط أزواج مجموعة مكرر. وانها عادة ما تكون في نطاق محدود جدا.

وكل شيء قبيح جدا وhacky تبحث بالمقارنة مع شيء من هذا القبيل هاسكل أو بايثون. عندما يحصل C ++ 0X هنا ونحصل على ستبدأ "السيارات" الصفوف الكلمة للنظر الكثير أكثر جاذبية.

وفائدة من المجموعات تتناسب عكسيا مع عدد من ضربات المفاتيح اللازمة لتعلن، حزمة، وافتح لهم.

وبالنسبة لي، انها عادة، الأيدي: التيوبل لا حل أي مشاكل جديدة بالنسبة لي، وهذا قليل من كثير لا أستطيع التعامل مع بالفعل على ما يرام. مبادلة القيم لا يزال يشعر أسهل بالطريقة القديمة - والأهم من ذلك، لا أعتقد حقا حول كيفية مبادلة "أفضل". انها جيدة بما فيه الكفاية كما هو.

وشخصيا، لا أعتقد الصفوف هي حل كبير للعودة قيم متعددة - يبدو وكأنه عمل للstructs

<ط> ولكن ماذا لو كنت تريد لتدوير ثلاث قيم؟

swap(a,b);
swap(b,c);  // I knew those permutation theory lectures would come in handy.

وOK، وذلك مع القيم 4 الخ، في نهاية المطاف ن الصفوف (tuple) يصبح أقل رمز من ن 1 مقايضة. ومع مقايضة التخلف عن سداد هذا لا 6 المهام بدلا من 4 كنت قد إذا كنت تنفذ قالب ثلاثي المراحل نفسك، وإن كنت آمل أن المترجم حل أن لأنواع بسيطة.

ويمكنك الخروج مع سيناريوهات حيث مقايضة هي غير عملي أو غير لائقة، على سبيل المثال:

tie(a,b,c) = make_tuple(b*c,a*c,a*b);

وهو محرجا بعض الشيء إلى فك.

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

tie(a,b,c) = make_tuple(b,c,a);

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

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

كما أشار العديد من الأشخاص، فإن الصفوف ليست مفيدة مثل الميزات الأخرى.

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

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

وليس كل من يمكن استخدام دفعة وTR1 غير متوفرة على نطاق واسع حتى الآن.

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

ونادرا ما نراهم لأن كود مصممة تصميما جيدا عادة لا يحتاج them- لا يوجد لكثير من الحالات في البرية حيث استخدام البنية مجهولة متفوقة على استخدام عين واحدة. منذ جميعا الصفوف (tuple) يمثل حقا هو بنية مجهولة، ومعظم المبرمجون في معظم الحالات اذهبوا مع الشيء الحقيقي.

ويقول لدينا وظيفة "و" حيث أصبحت العودة الصفوف (tuple) قد يكون له معنى. وكقاعدة عامة، وعادة ما تكون معقدة مثل هذه الوظائف ما يكفي أنها يمكن أن تفشل.

إذا "و" يمكن أن تفشل، كنت في حاجة الى return- الوضع بعد كل شيء، كنت لا تريد المتصلين أن يكون لتفقد كل معلمة للكشف عن الفشل. "و" ربما يلائم نمط:

struct ReturnInts ( int y,z; }
bool f(int x, ReturnInts& vals);

int x = 0;
ReturnInts vals;
if(!f(x, vals)) {
    ..report error..
    ..error handling/return...
}

وهذا ليس جميلا، ولكن ننظر في كيفية القبيح البديل. علما بأنني لا تزال بحاجة إلى قيمة الحالة، ولكن هو رمز لا أكثر قابلية للقراءة وليس أقصر. وربما هو أبطأ جدا، منذ أن تتحمل تكلفة 1 نسخة مع الصفوف (tuple).

std::tuple<int, int, bool> f(int x);
int x = 0;
std::tuple<int, int, bool> result = f(x); // or "auto result = f(x)"
if(!result.get<2>()) {
    ... report error, error handling ...
}

وآخر، يتم إخفاء الهبوط الكبير في هنا- مع "ReturnInts" يمكنني أن أضيف تغيير "و" الصورة العودة عن طريق تعديل "ReturnInts" دون تغيير "و" الصورة INTERFACE. الحل الصفوف (tuple) لا تقدم هذه الميزة الهامة، مما يجعل من الإجابة أدنى للأي رمز المكتبة.

وبالتأكيد الصفوف يمكن أن تكون مفيدة، ولكن كما ذكرت هناك قليلا من النفقات العامة وعقبة أو اثنين لديك من خلال القفز قبل أن تتمكن من استخدام حتى حقا لهم.

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

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

وكما std::tuple متجر البيانات لديها أسوأ خصائص كل من struct ومجموعة. وصول جميع وموقف الألف مقرها لكن المرء لا يستطيع تكرار خلال tuple باستخدام حلقة for.

وإذا كان الأمر كذلك العناصر في tuple هي المفهوم صفيف، وسوف تستخدم مجموعة وإذا كانت العناصر ليست من الناحية النظرية صفيف، البنية (الذي يدعى العناصر) أكثر للصيانة. (a.lastname هو أكثر تفسيرية من std::get<1>(a)).

وهذا يترك التحول من OP المذكورة باعتبارها نموذج التطبيقي الوحيد القابل للتطبيق لالصفوف.

ولدي شعور بأن استخدام العديد من Boost.Any وBoost.Variant (مع بعض الهندسة) بدلا من Boost.Tuple.

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