سوالات مصاحبه C++ – انجمن DEV

Summarize this content to 400 words in Persian Lang
مقدمه
این یک مقاله بعدی برای سؤالات مصاحبه C است، بنابراین اگر آن را نخوانده اید، باید آن را مطالعه کنید. همانطور که در آنجا گفته شد، تمام آن سوالات C نیز سوالات معتبر C++ هستند، بنابراین می توان از داوطلبی که برای یک شغل C++ مصاحبه می کند، پرسید. البته C++ یک زبان بسیار بزرگتر از C است، بنابراین چندین سوال اضافی وجود دارد که مختص C++ هستند.
در اینجا چند سوال (همراه با پاسخ) وجود دارد که از یک نامزد در طول مصاحبه برای برنامه نویسی شغلی در C++ (علاوه بر سوالات C) می پرسم.
مانند قبل، اگر مبتدی هستید، توصیه می کنم قبل از کلیک کردن بر روی آن، سعی کنید به سوالات خود پاسخ دهید پاسخ دهید پیوندها
سوالات
سوال 1: متغیرهای محلی
با توجه به این تابع (where T یک نوع دلخواه است که در اینجا مهم نیست):
T& f() {
T t;
// …
return t;
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
سوال: این تابع چه مشکلی دارد؟
این سوال اساساً همان سوال مصاحبه شماره 4 C است به جز اینکه منابع جایگزین نشانگرها می شوند.
پاسخ دهید
چون t یک متغیر محلی است، پس از بازگشت وجود خود را از دست خواهد داد، بنابراین مرجع a خواهد بود مرجع آویزان. تلاش برای دسترسی به مقدار ارجاع شده منجر به رفتار نامشخص می شود (و اگر خوش شانس باشید احتمالاً منجر به تخلیه اصلی می شود).
سوال 2: delete
چی دو وقتی تماس می گیرید اتفاقاتی می افتد delete?
پاسخ دهید
ویرانگر شی، در صورت وجود، فراخوانی می شود.
حافظه ای که شی مورد استفاده قرار می دهد اختصاص داده می شود.
سوال 3: delete[]
چه فرقی با هم دارند delete و delete[]?
پاسخ دهید
دشت delete برای از بین بردن یک شی منفرد استفاده می شود. delete[] برای از بین بردن مجموعه ای از اشیاء استفاده می شود.
سوال 4: اپراتورهای واگذاری
با توجه به دو کلاس ++C:
struct T {
T( T const& );
~T();
};
struct S {
T *p; // may be null
S& operator=( S const &that ) {
// …
}
~S() { delete p; }
};
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
سوال 4 الف: عملگر انتساب کلاس را پیاده سازی کنید S به گونه ای که الف را اجرا می کند کپی عمیق، یعنی:
S x, y;
// …
x = y; // x.p points to a copy of *y.p, if any
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
یادداشت ها:
این p عضو یک است دارای اشاره گر، یعنی S مسئول است به صورت پویا تخصیص، اشاره کرد T.
شما می توانید فقط از آن توابعی که به صراحت در اینجا اعلام شده است استفاده کنید.
جزئیات کلاس T مهم نیست فرض کنید که T(T const&) کپی های الف T به طور متعارف اعتراض کنید.
پاسخ دهید
یک پیاده سازی اولیه ممکن است:
S& S::operator=( S const &that ) {
if ( &that != this ) { // 2
delete p; // 3
p = that.p ? new T( *that.p ) : nullptr; // 4
}
return *this; // 6
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
خط 2 از خود واگذاری محافظت می کند، یعنی:
x = x; // silly, but it still has to be correct
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
خط 3 موجود را حذف می کند T، در صورت وجود
هست هرگز لازم است قبل از حذف یک اشاره گر از نظر null بررسی شود. C++ تضمین می کند که حذف یک اشاره گر تهی هیچ کاری نمی کند.
خط 4 آن را بررسی می کند that.p غیر پوچ است (همانطور که داده شد، p ممکن است null باشد) و به صورت پویا یک کپی از آن را اختصاص می دهد *p اگر نه در غیر این صورت، فقط مجموعه p باطل شدن
خط 5 برمی گردد *this همانطور که تمام اپراتورهای انتساب انجام می دهند.
سوال 4 ب ( ارشد): آیا اجرای استثنایی ایمن است؟ اگر نه، چگونه آن را ایمن میکنید؟
پاسخ دهید
پاسخ قبلی این است نه استثنا-ایمن زیرا اگر T(T const&) یک استثنا می اندازد T به که p امتیازها قبلاً حذف شده اند.
برای ایمن بودن در برابر استثنا، یک تابع باید طوری رفتار کند که گویی هیچ اتفاقی نیفتاده است. در این حالت اپراتور تخصیص باید نه را حذف کنید T به که p امتیاز
برای ایمن کردن آن در برابر استثنا، یک متغیر موقت معرفی کنید:
S& S::operator=( S const &that ) {
if ( &that != this ) {
T *t = that.p ? new T( *that.p ) : nullptr;
delete p; // 4
p = t;
}
return *this;
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
حالا به جای حذف p ابتدا تماس بگیرید T(T const&) اول اگر یک استثنا ایجاد کند، خط 4 هرگز به آن نمی رسد. اگر کد به خط 4 رسید، به این معنی است که رسیده است نه یک استثنا پرتاب کنید اکنون حذف آن بی خطر است p.
سوال 4c ( ارشد): چی دو اگر این کار را انجام دهیم عواقب بدی در پی خواهد داشت نه اجرا کنند S::operator=(S const&)?
پاسخ دهید
بدون اجرای عملگر انتساب خودمان، کامپایلر به طور خودکار یک پیش فرض را ترکیب می کند که این کار را انجام می دهد. کپی کم عمق، که به سادگی مقدار the را کپی کنید p و نه را T به که p امتیاز این دو پیامد بد دارد:
سمت چپ T بلافاصله حافظه لو خواهد رفت.
سمت چپ و راست دست p به اشاره خواهد کرد همان T. وقتی اولین S نابود می شود، حذف می شود T. وقتی دومی S نابود می شود، سعی می کند آن را حذف کند T که دارد در حال حاضر حذف شده است. این به احتمال زیاد منجر به تخلیه هسته ای می شود.
سوال 5: std::map در مقابل std::unordered_map
چه تفاوت هایی وجود دارد std::map و std::unordered_map از نظر نحوه اجرای آنها معمولاً، زمان اجرا (نماد “O” بزرگ)، و زمانی که از یکی در مقابل دیگری استفاده می کنید؟
پاسخ دهید
std::map معمولاً با استفاده از یک درخت باینری متعادل اجرا می شود، به عنوان مثال، یک درخت قرمز-مشکی، که هم میانگین و هم بدترین زمان درج، جستجو و حذف برای آن همه است. O (log n).
std::unordered_map با استفاده از جدول هش اجرا می شود که میانگین زمان درج، جستجو و حذف برای آن همه است. O (1)، اما بدترین زمان ها همه آنها هستند O(n).
تکرار بیش از a map آیتم ها را به ترتیب مرتب شده برمی گرداند در حالی که تکرار بر روی یک unordered_map (همانطور که از نامش پیداست) ندارد.
به طور کلی، unordered_map به دلیل ترجیح داده می شود O(1) میانگین زمان عملکرد با این حال، اگر نیاز به تکرار به ترتیب مرتب شده دارید، باید از آن استفاده کنید map – اما این مستلزم این است که موارد وجود داشته باشند کمتر از قابل مقایسه.
سوال 6: virtual توابع
توابع مجازی معمولاً توسط کامپایلرهای C++ چگونه پیاده سازی می شوند؟
پاسخ دهید
هر کلاسی که حداقل یک تابع مجازی دارد، یک تابع مرتبط دارد vtbl (“جدول vee”) با یک “اسلات” برای هر تابع مجازی (از جمله تخریب کننده).
هر شکاف حاوی یک اشاره گر به تابع از اجرای لغو شده آن کلاس از تابع است. (اگر یک کلاس خاص تابع مجازی کلاس پایه خود را باطل نکند، در آن صورت شکاف آن حاوی یک اشاره گر به تابع پایه است.)
سپس هر شی از چنین کلاسی حاوی a است vptr (“اشاره گر vee”) که به vtbl برای کلاسش مقدار این اشاره گر نوع شی را در زمان اجرا تعیین می کند.
سوال 7: خطا را تشخیص دهید
داده شده:
struct S {
// Hint: the error is in the next line.
S() : p1{ new T }, p2{ new T } {
}
~S() {
delete p1;
delete p2;
}
T *p1, *p2;
};
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
سوال 7a ( ارشد): اون کلاس چه مشکلی داره؟
پاسخ دهید
اگر T::T() در طول ساخت یک استثنا می اندازد p2، p1 نشت خواهد کرد زیرا تخریب کننده ها هستند نه فراخوانی شده برای اشیاء نیمه ساخته شده (در این مورد S، از این رو ~S() خواهد شد نه اجرا و delete p1 هرگز نامیده نخواهد شد).
سوال 7 ب ( ارشد): چطوری درستش میکنی؟
پاسخ دهید
شاید ساده ترین راه برای رفع این مشکل استفاده از آن باشد std::unique_ptr:
struct S {
S() : p1{ new T }, p2{ new T } {
}
std::unique_ptrT> p1, p2;
};
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
حتی اگر تخریب کننده بر روی اشیایی که سازنده (یا سازنده یک عضو داده) آنها را پرتاب می کند، فراخوانی نمی شود، تخریب کننده ها هستند اعضای داده کاملاً ساخته شده را فراخواند.
در این مورد، p1ویرانگر نامیده می شود (در نتیجه آزاد می شود p1) اگر p2سازنده پرتاب می کند.
سوال 8: new
داده شده:
T *t = new( p ) T;
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
سوال 8a ( ارشد): این نحو به چه معناست؟
پاسخ دهید
به عنوان شناخته شده است قرار دادن جدید و برای ایجاد یک شی در یک آدرس حافظه خاص استفاده می شود، در این مورد، حافظه اشاره شده توسط p.
سوال 8 ب ( ارشد): در صورت وجود چه محدودیت(هایی) دارد؟
پاسخ دهید
آدرس باید متناسب با نوع شی در حال ساخت و اندازه کافی تراز باشد.
سوال 8c ( ارشد): چگونه چنین شیئی را از بین می برید؟
پاسخ دهید
شما باید صراحتاً ویرانگر آن را مانند:
t->~T();
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
نتیجه گیری
اینها برخی از سوالات مصاحبه C++ مناسب هستند. هنگام مصاحبه با نامزدها به راحتی از آنها استفاده کنید.
مقدمه
این یک مقاله بعدی برای سؤالات مصاحبه C است، بنابراین اگر آن را نخوانده اید، باید آن را مطالعه کنید. همانطور که در آنجا گفته شد، تمام آن سوالات C نیز سوالات معتبر C++ هستند، بنابراین می توان از داوطلبی که برای یک شغل C++ مصاحبه می کند، پرسید. البته C++ یک زبان بسیار بزرگتر از C است، بنابراین چندین سوال اضافی وجود دارد که مختص C++ هستند.
در اینجا چند سوال (همراه با پاسخ) وجود دارد که از یک نامزد در طول مصاحبه برای برنامه نویسی شغلی در C++ (علاوه بر سوالات C) می پرسم.
مانند قبل، اگر مبتدی هستید، توصیه می کنم قبل از کلیک کردن بر روی آن، سعی کنید به سوالات خود پاسخ دهید پاسخ دهید پیوندها
سوالات
سوال 1: متغیرهای محلی
با توجه به این تابع (where T
یک نوع دلخواه است که در اینجا مهم نیست):
T& f() {
T t;
// ...
return t;
}
سوال: این تابع چه مشکلی دارد؟
این سوال اساساً همان سوال مصاحبه شماره 4 C است به جز اینکه منابع جایگزین نشانگرها می شوند.
پاسخ دهید
چون t
یک متغیر محلی است، پس از بازگشت وجود خود را از دست خواهد داد، بنابراین مرجع a خواهد بود مرجع آویزان. تلاش برای دسترسی به مقدار ارجاع شده منجر به رفتار نامشخص می شود (و اگر خوش شانس باشید احتمالاً منجر به تخلیه اصلی می شود).
سوال 2: delete
چی دو وقتی تماس می گیرید اتفاقاتی می افتد delete
?
پاسخ دهید
- ویرانگر شی، در صورت وجود، فراخوانی می شود.
- حافظه ای که شی مورد استفاده قرار می دهد اختصاص داده می شود.
سوال 3: delete[]
چه فرقی با هم دارند delete
و delete[]
?
پاسخ دهید
دشت delete
برای از بین بردن یک شی منفرد استفاده می شود. delete[]
برای از بین بردن مجموعه ای از اشیاء استفاده می شود.
سوال 4: اپراتورهای واگذاری
با توجه به دو کلاس ++C:
struct T {
T( T const& );
~T();
};
struct S {
T *p; // may be null
S& operator=( S const &that ) {
// ...
}
~S() { delete p; }
};
سوال 4 الف: عملگر انتساب کلاس را پیاده سازی کنید S
به گونه ای که الف را اجرا می کند کپی عمیق، یعنی:
S x, y;
// ...
x = y; // x.p points to a copy of *y.p, if any
یادداشت ها:
- این
p
عضو یک است دارای اشاره گر، یعنیS
مسئول است به صورت پویا تخصیص، اشاره کردT
. - شما می توانید فقط از آن توابعی که به صراحت در اینجا اعلام شده است استفاده کنید.
- جزئیات کلاس
T
مهم نیست فرض کنید کهT(T const&)
کپی های الفT
به طور متعارف اعتراض کنید.
پاسخ دهید
یک پیاده سازی اولیه ممکن است:
S& S::operator=( S const &that ) {
if ( &that != this ) { // 2
delete p; // 3
p = that.p ? new T( *that.p ) : nullptr; // 4
}
return *this; // 6
}
خط 2 از خود واگذاری محافظت می کند، یعنی:
x = x; // silly, but it still has to be correct
خط 3 موجود را حذف می کند T
، در صورت وجود
هست هرگز لازم است قبل از حذف یک اشاره گر از نظر null بررسی شود. C++ تضمین می کند که حذف یک اشاره گر تهی هیچ کاری نمی کند.
خط 4 آن را بررسی می کند that.p
غیر پوچ است (همانطور که داده شد، p
ممکن است null باشد) و به صورت پویا یک کپی از آن را اختصاص می دهد *p
اگر نه در غیر این صورت، فقط مجموعه p
باطل شدن
خط 5 برمی گردد *this
همانطور که تمام اپراتورهای انتساب انجام می دهند.
سوال 4 ب ( ارشد): آیا اجرای استثنایی ایمن است؟ اگر نه، چگونه آن را ایمن میکنید؟
پاسخ دهید
پاسخ قبلی این است نه استثنا-ایمن زیرا اگر T(T const&)
یک استثنا می اندازد T
به که p
امتیازها قبلاً حذف شده اند.
برای ایمن بودن در برابر استثنا، یک تابع باید طوری رفتار کند که گویی هیچ اتفاقی نیفتاده است. در این حالت اپراتور تخصیص باید نه را حذف کنید T
به که p
امتیاز
برای ایمن کردن آن در برابر استثنا، یک متغیر موقت معرفی کنید:
S& S::operator=( S const &that ) {
if ( &that != this ) {
T *t = that.p ? new T( *that.p ) : nullptr;
delete p; // 4
p = t;
}
return *this;
}
حالا به جای حذف p
ابتدا تماس بگیرید T(T const&)
اول اگر یک استثنا ایجاد کند، خط 4 هرگز به آن نمی رسد. اگر کد به خط 4 رسید، به این معنی است که رسیده است نه یک استثنا پرتاب کنید اکنون حذف آن بی خطر است p
.
سوال 4c ( ارشد): چی دو اگر این کار را انجام دهیم عواقب بدی در پی خواهد داشت نه اجرا کنند S::operator=(S const&)
?
پاسخ دهید
بدون اجرای عملگر انتساب خودمان، کامپایلر به طور خودکار یک پیش فرض را ترکیب می کند که این کار را انجام می دهد. کپی کم عمق، که به سادگی مقدار the را کپی کنید p
و نه را T
به که p
امتیاز این دو پیامد بد دارد:
- سمت چپ
T
بلافاصله حافظه لو خواهد رفت. - سمت چپ و راست دست
p
به اشاره خواهد کرد همانT
. وقتی اولینS
نابود می شود، حذف می شودT
. وقتی دومیS
نابود می شود، سعی می کند آن را حذف کندT
که دارد در حال حاضر حذف شده است. این به احتمال زیاد منجر به تخلیه هسته ای می شود.
سوال 5: std::map
در مقابل std::unordered_map
چه تفاوت هایی وجود دارد std::map
و std::unordered_map
از نظر نحوه اجرای آنها معمولاً، زمان اجرا (نماد “O” بزرگ)، و زمانی که از یکی در مقابل دیگری استفاده می کنید؟
پاسخ دهید
std::map
معمولاً با استفاده از یک درخت باینری متعادل اجرا می شود، به عنوان مثال، یک درخت قرمز-مشکی، که هم میانگین و هم بدترین زمان درج، جستجو و حذف برای آن همه است. O (log n).
std::unordered_map
با استفاده از جدول هش اجرا می شود که میانگین زمان درج، جستجو و حذف برای آن همه است. O (1)، اما بدترین زمان ها همه آنها هستند O(n).
تکرار بیش از a map
آیتم ها را به ترتیب مرتب شده برمی گرداند در حالی که تکرار بر روی یک unordered_map
(همانطور که از نامش پیداست) ندارد.
به طور کلی، unordered_map
به دلیل ترجیح داده می شود O(1)
میانگین زمان عملکرد با این حال، اگر نیاز به تکرار به ترتیب مرتب شده دارید، باید از آن استفاده کنید map
– اما این مستلزم این است که موارد وجود داشته باشند کمتر از قابل مقایسه.
سوال 6: virtual
توابع
توابع مجازی معمولاً توسط کامپایلرهای C++ چگونه پیاده سازی می شوند؟
پاسخ دهید
هر کلاسی که حداقل یک تابع مجازی دارد، یک تابع مرتبط دارد vtbl (“جدول vee”) با یک “اسلات” برای هر تابع مجازی (از جمله تخریب کننده).
هر شکاف حاوی یک اشاره گر به تابع از اجرای لغو شده آن کلاس از تابع است. (اگر یک کلاس خاص تابع مجازی کلاس پایه خود را باطل نکند، در آن صورت شکاف آن حاوی یک اشاره گر به تابع پایه است.)
سپس هر شی از چنین کلاسی حاوی a است vptr (“اشاره گر vee”) که به vtbl برای کلاسش مقدار این اشاره گر نوع شی را در زمان اجرا تعیین می کند.
سوال 7: خطا را تشخیص دهید
داده شده:
struct S {
// Hint: the error is in the next line.
S() : p1{ new T }, p2{ new T } {
}
~S() {
delete p1;
delete p2;
}
T *p1, *p2;
};
سوال 7a ( ارشد): اون کلاس چه مشکلی داره؟
پاسخ دهید
اگر T::T()
در طول ساخت یک استثنا می اندازد p2
، p1
نشت خواهد کرد زیرا تخریب کننده ها هستند نه فراخوانی شده برای اشیاء نیمه ساخته شده (در این مورد S
، از این رو ~S()
خواهد شد نه اجرا و delete p1
هرگز نامیده نخواهد شد).
سوال 7 ب ( ارشد): چطوری درستش میکنی؟
پاسخ دهید
شاید ساده ترین راه برای رفع این مشکل استفاده از آن باشد std::unique_ptr
:
struct S {
S() : p1{ new T }, p2{ new T } {
}
std::unique_ptrT> p1, p2;
};
حتی اگر تخریب کننده بر روی اشیایی که سازنده (یا سازنده یک عضو داده) آنها را پرتاب می کند، فراخوانی نمی شود، تخریب کننده ها هستند اعضای داده کاملاً ساخته شده را فراخواند.
در این مورد، p1
ویرانگر نامیده می شود (در نتیجه آزاد می شود p1
) اگر p2
سازنده پرتاب می کند.
سوال 8: new
داده شده:
T *t = new( p ) T;
سوال 8a ( ارشد): این نحو به چه معناست؟
پاسخ دهید
به عنوان شناخته شده است قرار دادن جدید و برای ایجاد یک شی در یک آدرس حافظه خاص استفاده می شود، در این مورد، حافظه اشاره شده توسط p
.
سوال 8 ب ( ارشد): در صورت وجود چه محدودیت(هایی) دارد؟
پاسخ دهید
آدرس باید متناسب با نوع شی در حال ساخت و اندازه کافی تراز باشد.
سوال 8c ( ارشد): چگونه چنین شیئی را از بین می برید؟
پاسخ دهید
شما باید صراحتاً ویرانگر آن را مانند:
t->~T();
نتیجه گیری
اینها برخی از سوالات مصاحبه C++ مناسب هستند. هنگام مصاحبه با نامزدها به راحتی از آنها استفاده کنید.