العودة من وظيفة الفراغ في C ++
سؤال
النظر في المقتطف التالي:
void Foo()
{
// ...
}
void Bar()
{
return Foo();
}
ما هو السبب المشروع لاستخدام ما سبق في C ++ بدلاً من النهج الأكثر شيوعًا:
void Foo()
{
// ...
}
void Bar()
{
Foo();
// no more expressions -- i.e., implicit return here
}
المحلول
ربما لا فائدة في مثالك ، ولكن هناك بعض المواقف التي يصعب التعامل معها void
في رمز القالب ، وأتوقع أن تساعد هذه القاعدة في ذلك في بعض الأحيان. مثال مفتعل جدا:
#include <iostream>
template <typename T>
T retval() {
return T();
}
template <>
void retval() {
return;
}
template <>
int retval() {
return 23;
}
template <typename T>
T do_something() {
std::cout << "doing something\n";
}
template <typename T>
T do_something_and_return() {
do_something<T>();
return retval<T>();
}
int main() {
std::cout << do_something_and_return<int>() << "\n";
std::cout << do_something_and_return<void*>() << "\n";
do_something_and_return<void>();
}
لاحظ ذلك فقط main
يجب أن تتعامل مع حقيقة أنه في void
حالة لا يوجد شيء للعودة من retval
. الوظيفة الوسيطة do_something_and_return
عام.
بالطبع هذا يحصل عليك حتى الآن - إذا do_something_and_return
مطلوب ، في الحالة العادية ، للتخزين retval
في متغير وافعل شيئًا معه قبل العودة ، ستظل في ورطة - يجب أن تتخصص (أو الحمل الزائد) do_something_and_return
للباطل.
نصائح أخرى
هذا بناء غير مجدي إلى حد ما لا يخدم أي غرض ، ما لم يتم استخدامه مع القوالب. أي إذا كنت قد حددت وظائف القالب التي تُرجع قيمة قد تكون "باطلة".
يمكنك استخدامه في التعليمات البرمجية العامة ، حيث تكون قيمة إرجاع FOO () غير معروفة أو تخضع للتغيير. انصح:
template<typename Foo, typename T> T Bar(Foo f) {
return f();
}
في هذه الحالة ، يكون الشريط صالحًا للفراغ ، ولكنه صالح أيضًا في حالة تغيير نوع الإرجاع. ومع ذلك ، إذا كان يطلق عليه فقط f ، فإن هذا الرمز سوف ينهار إذا كان t غير void. باستخدام العودة f () ؛ يضمن بناء الجملة الحفاظ على قيمة الإرجاع لـ FOO () إذا كان هناك واحد ، ويسمح بالفراغ ().
بالإضافة إلى ذلك ، فإن العودة بشكل صريح هي عادة جيدة للدخول.
قوالب:
template <typename T, typename R>
R some_kind_of_wrapper(R (*func)(T), T t)
{
/* Do something interesting to t */
return func(t);
}
int func1(int i) { /* ... */ return i; }
void func2(const std::string& str) { /* ... */ }
int main()
{
int i = some_kind_of_wrapper(&func1, 42);
some_kind_of_wrapper(&func2, "Hello, World!");
return 0;
}
دون أن تكون قادرًا على إعادة الفراغ ، return func(t)
في القالب لن يعمل عندما طُلب منه الالتفاف func2
.
السبب الوحيد الذي يمكنني التفكير فيه هو إذا كان لديك قائمة طويلة من return Foo();
عبارات في مفتاح وأراد جعلها أكثر إحكاما.
والسبب هو إرجاع الذاكرة مثل Math.h يعود دائمًا. Math.h ليس لديه فراغ ولا حجج فارغة. هناك العديد من المواقف العملية التي تحتاج فيها إلى الذاكرة.
يمكن أن تكون حالة حيث Foo()
أعاد في الأصل قيمة ، ولكن تم تغييره لاحقًا إلى void
, والشخص الذي قام بتحديثه لم يفكر بوضوح شديد.