Как удаляется vptr?
От: avovana Россия  
Дата: 10.04.23 16:33
Оценка: :)
Привет с собеседования в тинькове.

Где есть вообще этот vptr?
Если делаем объект базового класса, у которого хотя бы 1 функция virtual, то компилятор добавит ему vptr.
Размер такого класса(если нет других членов) станет из 1 байта -> sizeof(vptr).
Если делаем объект класса наследника от такого базового класса, то компилятор добавит ему vptr. У него не будет ещё 1ого vptr от базового. А будет свой vptr.
Т.е. это член объекта наследника.
Что если удаляем теперь наследника как в коде ниже. То есть, не будет вызван деструктор класса наследника. Что станет с этим vptr объекта класса наследника? Утечёт?

#include <iostream> 
   
class Base { 
    virtual void print() {std::cout << "from Base" << std::endl;} 
public: 
    Base() {print();} 
    virtual ~Base() { print(); } 
    void basePrint() { print(); } 
}; 
   
class Derived : public Base { 
    virtual void print() {std::cout << "from Derived" << std::endl;} 
public: 
    Derived () { print(); } 
    ~Derived () { print(); } 
}; 
   
int main(void) { 
    Base* base = new Derived; 
    base->basePrint(); 
    delete base; 
    return 0; 
}


Видел пример в интернете, что vptr 1 в базовом классе. Наследуется наследниками. Т.е. деструктор базового класса по любому вызовется. И удалит этот vptr.

Ещё как-то был вопрос: "Где хранится таблица виртуальных методов?".
P.S. ещё спрашивали "из чего состоит указатель? как работает?".
Отредактировано 10.04.2023 16:38 avovana . Предыдущая версия . Еще …
Отредактировано 10.04.2023 16:36 avovana . Предыдущая версия .
Отредактировано 10.04.2023 16:35 avovana . Предыдущая версия .
Re: Как удаляется vptr?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 10.04.23 16:43
Оценка:
Здравствуйте, avovana, Вы писали:

Какая-то каша в голове.

vtbl — это статическая таблица (массив) указателей на методы класса, vptr — просто указывает на эту таблицу. Никакого удаления и создания не происходит. Если класс создаётся хотя бы единожды, то появляется ссылка на его vtbl и соответственно, она прилинковывается, иначе — нет.

Проблема с виртуальным деструктором в том, что если его нет, при удалении через указатель на базу производится вызов конкретного деструктора базового класса, и мемберы производного класса не будут корректно разрушены. Если в производном классе нет доп полей или они тривиальные, то программа в целом даже будет хромать и дальше. Если там что-то повеселее, хотя бы string или vector — то их деструкторы не будут вызваны и память будет утекать. Но причем тут vptr, и что подразумевается под его утечкой?


ЗЫ А чего, в тиньке на плюсах пишут? По-моему, там Java изо всех дырок торчит. Что за вакансия, какая компенсация?
Маньяк Робокряк колесит по городу
Отредактировано 10.04.2023 16:44 Marty . Предыдущая версия .
Re: Как удаляется vptr?
От: rg45 СССР  
Дата: 10.04.23 17:40
Оценка:
Здравствуйте, avovana, Вы писали:

A>Где есть вообще этот vptr?


С уверенностью можно сказать лишь то, что он определен для каждого объекта (по одному на каждый объект). То есть, имея указатель или сылку на объект базового или любого из производных классов, можно получить указатель на таблицу виртуальных функций объекта. А какой размер и формат имеет этот указатель, и в каком месте объекта он располагается (в начале, в конце или вообще в какой-нибудь внешней мапе) — это уже implementation defined, об этом знает только компилятор. Таблицы виртуальных функций являютсся внешними по отношению к объектам. Объекты, имеющие одинаковый статический тип (класс) имеют одинаковый vptr, указывающий на одну и ту же таблицу виртуальных функций.

A>Если делаем объект базового класса, у которого хотя бы 1 функция virtual, то компилятор добавит ему vptr.

A>Размер такого класса(если нет других членов) станет из 1 байта -> sizeof(vptr).

Пока все правильно.

A>Если делаем объект класса наследника от такого базового класса, то компилятор добавит ему vptr. У него не будет ещё 1ого vptr от базового. А будет свой vptr.

A>Т.е. это член объекта наследника.

А вот тут немного по-другому: все производные классы вместе с базовым используют один и тот же указатель vptr, но в зависимости от реального (статического) типа объекта, в этом поле будут записаны разные указатели на разные виртуальные таблицы. Когда объект конструируется, вызываются последовательно конструкторы разных уровней — от базового к самому последнему производному. Внутри каждого конструктора, vptr указывает на таблицу виртуальных функций, соответствующую тому классу, который конструируется в данный момент. , При перехода от одного конструктора к другому, изменяется и значение vptr. Этот процесс изменения vptr можно отследить теми или иными отладочными трюками, если предварительно вычислить (не очень законными способами) формат и место расположения vptr в объекте. При разрушении объекта происходит обратный процесс: последовательно вызываются деструкторы от самого последного произодного до базого и при этом так же меняются значения vptr, но уже в обратном порядке. И вот поэтому нельзя вызвать виртуальную фунцию производного класса из конструктора или деструктора базового класса. Точнее, вызвать то можно, но вызовется функция, соответстующая текущему значению vptr.

A>Что если удаляем теперь наследника как в коде ниже. То есть, не будет вызван деструктор класса наследника. Что станет с этим vptr объекта класса наследника? Утечёт?


А при удалении объекта по указателю на базовый класс, код, сгенерированный компилятором, воспользуется значением vptr, хранящимся в объекте и по таблице виртуальных функций вызовет виртуальный деструктор самого последнего производного класса. А тот, в свою очередь инициирует всю цепочку деструкторов до самого базового класса (уже без использования виртуального механизма). После того, как цепочка деструкторов завершится, будет освобождена память, занимаемая объектом.

Что еще важно помнить, что если деструктор базового класса объявлен виртуальным, то деструкторы всех производных классов также будут виртуальными, независимо от того, использовалось ли ключевое слово virtual при их объявлении.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 10.04.2023 17:59 rg45 . Предыдущая версия . Еще …
Отредактировано 10.04.2023 17:54 rg45 . Предыдущая версия .
Отредактировано 10.04.2023 17:52 rg45 . Предыдущая версия .
Отредактировано 10.04.2023 17:47 rg45 . Предыдущая версия .
Отредактировано 10.04.2023 17:46 rg45 . Предыдущая версия .
Отредактировано 10.04.2023 17:46 rg45 . Предыдущая версия .
Отредактировано 10.04.2023 17:42 rg45 . Предыдущая версия .
Отредактировано 10.04.2023 17:40 rg45 . Предыдущая версия .
Re[2]: Как удаляется vptr?
От: okman Беларусь https://searchinform.ru/
Дата: 10.04.23 18:30
Оценка:
Здравствуйте, Marty, Вы писали:

M>Проблема с виртуальным деструктором в том, что если его нет, при удалении через указатель на базу производится вызов конкретного деструктора базового класса, и мемберы производного класса не будут корректно разрушены. Если в производном классе нет доп полей или они тривиальные, то программа в целом даже будет хромать и дальше. Если там что-то повеселее, хотя бы string или vector — то их деструкторы не будут вызваны и память будет утекать.


Строго говоря, полиморфное (т.е. через указатель на базу) удаление объекта при отсутствии виртуального деструктора — это undefined behavior.
Не так уж трудно придумать кейс, где вместо утечки будет segfault / access violation на большинстве компиляторов. Хотя, опять же, полагаться на это нельзя, т.к. UB есть UB.
Имеется в виду что-то типа такого:
struct Dad
{
    // virtual ~Dad() {}
    virtual void power() {}
};

struct Mom
{
    // virtual ~Mom() {}
    virtual void love() {}
};

struct Kid : Dad, Mom
{
};

int main()
{
    Mom * ptr = new Kid();
    delete ptr; // UB!!!
    return 0;
}
Re[3]: Как удаляется vptr?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 10.04.23 18:38
Оценка:
Здравствуйте, okman, Вы писали:

O>Строго говоря, полиморфное (т.е. через указатель на базу) удаление объекта при отсутствии виртуального деструктора — это undefined behavior.

O>Не так уж трудно придумать кейс, где вместо утечки будет segfault / access violation на большинстве компиляторов. Хотя, опять же, полагаться на это нельзя, т.к. UB есть UB.
O>Имеется в виду что-то типа такого:
  Скрытый текст
O>
O>struct Dad
O>{
O>    // virtual ~Dad() {}
O>    virtual void power() {}
O>};

O>struct Mom
O>{
O>    // virtual ~Mom() {}
O>    virtual void love() {}
O>};

O>struct Kid : Dad, Mom
O>{
O>};

O>int main()
O>{
O>    Mom * ptr = new Kid();
O>    delete ptr; // UB!!!
O>    return 0;
O>}
O>



При множественном наследовании конечно всё веселее будет довольно быстро. Я описывал самый простой случай единственного наследования, баги с которым могут жить годами
Маньяк Робокряк колесит по городу
Re[2]: Как удаляется vptr?
От: avovana Россия  
Дата: 10.04.23 18:39
Оценка:
Здравствуйте, Marty, Вы писали:

M>Проблема с виртуальным деструктором в том, что если его нет, при удалении через указатель на базу производится вызов конкретного деструктора базового класса, и мемберы производного класса не будут корректно разрушены. Если в производном классе нет доп полей или они тривиальные, то программа в целом даже будет хромать и дальше. Если там что-то повеселее, хотя бы string или vector — то их деструкторы не будут вызваны и память будет утекать. Но причем тут vptr, и что подразумевается под его утечкой?


Ну вот и спрашивают: "когда вызовется деструктор лишь базового класса, что будет с vptr класса наследника?" Как ты сказал, что деструкторы мемберов derived не будут вызваны. Того же вектора, если бы он был в derived. Память утечёт. А что будет тоже с мембером derived класса — его vptr?

M>ЗЫ А чего, в тиньке на плюсах пишут? По-моему, там Java изо всех дырок торчит. Что за вакансия, какая компенсация?

Рекомендательную систему для рекламы вроде. Нужно быстро давать пользователю нужную рекламу. Примерно так. Поэтому С++.
По компенсации, как понял, для senior сейчас в Мск 300+. Только лишь нужно доказать, что ты такой красный и спелый пройдя их фильтры)
Re[3]: Как удаляется vptr?
От: koenjihyakkei Россия  
Дата: 10.04.23 18:45
Оценка: +3
Здравствуйте, avovana, Вы писали:

A>По компенсации, как понял, для senior сейчас в Мск 300+. Только лишь нужно доказать, что ты такой красный и спелый пройдя их фильтры)


Вопрос про виртуальный деструктор это больше про junior
Re[2]: Как удаляется vptr?
От: avovana Россия  
Дата: 10.04.23 18:46
Оценка:
Здравствуйте, rg45, Вы писали:

R>А вот тут немного по-другому: все производные классы вместе с базовым используют один и тот же указатель vptr, но в зависимости от реального (статического) типа объекта, в этом поле будут записаны разные указатели на разные виртуальные таблицы. Когда объект конструируется, вызываются последовательно конструкторы разных уровней — от базового к самому последнему производному. Внутри каждого конструктора, vptr указывает на таблицу виртуальных функций, соответствующую тому классу, который конструируется в данный момент. , При перехода от одного конструктора к другому, изменяется и значение vptr. Этот процесс изменения vptr можно отследить теми или иными отладочными трюками, если предварительно вычислить (не очень законными способами) формат и место расположения vptr в объекте. При разрушении объекта происходит обратный процесс: последовательно вызываются деструкторы от самого последного произодного до базого и при этом так же меняются значения vptr, но уже в обратном порядке. И вот поэтому нельзя вызвать виртуальную фунцию производного класса из конструктора или деструктора базового класса. Точнее, вызвать то можно, но вызовется функция, соответстующая текущему значению vptr.


То есть правильно здесь представили что vptr лишь у базового. И наследники как-будто бы его наследуют?
class Base
{
public:
    FunctionPointer* __vptr;
    virtual void function1() {};
    virtual void function2() {};
};
 
class D1: public Base
{
public:
    virtual void function1() {};
};
 
class D2: public Base
{
public:
    virtual void function2() {};
};

https://radioprog.ru/post/1279
Тогда в случае не виртуального деструктора у базового класса как в топикстарте — "vptr не будет утекать". Интервьюер всё пытался понять от меня — будет ли он утекать или нет) Просто если у каждого он свой:
у base
у derived
то ведь если

Base *obj = new Derived // без virtual dtor
delete obj

То что будет с Derived vptr?
Re[3]: Как удаляется vptr?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 10.04.23 19:51
Оценка:
Здравствуйте, avovana, Вы писали:

A>Ну вот и спрашивают: "когда вызовется деструктор лишь базового класса, что будет с vptr класса наследника?" Как ты сказал, что деструкторы мемберов derived не будут вызваны. Того же вектора, если бы он был в derived. Память утечёт. А что будет тоже с мембером derived класса — его vptr?


Ничего не понял, опять сумбур какой-то


M>>ЗЫ А чего, в тиньке на плюсах пишут? По-моему, там Java изо всех дырок торчит. Что за вакансия, какая компенсация?

A>Рекомендательную систему для рекламы вроде. Нужно быстро давать пользователю нужную рекламу. Примерно так. Поэтому С++.
A>По компенсации, как понял, для senior сейчас в Мск 300+.

Вообще интересно. А куда стукнуть? Я б тоже сходил. В крайнем случае — принесу ещё ржаки на форум


A>Только лишь нужно доказать, что ты такой красный и спелый пройдя их фильтры)


Да это вообще не проблема Интересно посмотреть, что за народ, что за задачи
Маньяк Робокряк колесит по городу
Re[3]: Как удаляется vptr?
От: rg45 СССР  
Дата: 10.04.23 20:29
Оценка: +1
Здравствуйте, avovana, Вы писали:

A>То есть правильно здесь представили что vptr лишь у базового. И наследники как-будто бы его наследуют?


Да, на уровне идеи это можно представлять себе примерно так. Нужно только понимать, что ни сам vptr, ни таблица виртуальных функций, на которую он указывает, не доступны программисту. Эти структуры данных полностью управляются компилятором, и то, как они устроены, где располагаются, в какой момент и в какой области выделяется память под таблицы виртуальных функций и в какой момент эта память освобождается — об этом знает только компилятор и в разных компиляторах это может быть устроено по-разному.

A>
A>class Base
A>{
A>public:
A>    FunctionPointer* __vptr;
A>    virtual void function1() {};
A>    virtual void function2() {};
A>};

 
A>class D1: public Base
A>{
A>public:
A>    virtual void function1() {};
A>};
 
A>class D2: public Base
A>{
A>public:
A>    virtual void function2() {};
A>};
A>

A>https://radioprog.ru/post/1279
A>Тогда в случае не виртуального деструктора у базового класса как в топикстарте — "vptr не будет утекать". Интервьюер всё пытался понять от меня — будет ли он утекать или нет) Просто если у каждого он свой:
A>у base
A>у derived
A>то ведь если
A>
A>Base *obj = new Derived // без virtual dtor
A>delete obj
A>

A>То что будет с Derived vptr?

Я думаю, что по этой ссылке просто картинка неудачная, хотя на словах все написано правильно:

Компилятор также добавляет член скрытого указателя к самому базовому классу, который использует виртуальные функции. Хотя компилятор делает это автоматически, покажем в следующем примере, куда он добавляется:

Смысл же в том, чтоб, имея один только указатель на Base, код, построенный компилятором, смог бы доброаться до таблиц виртуальных функций ЛЮБЫХ производных классов. Очевидно, что одного угазателя на Base для этого недостаточно и нужна дополнительная информация, сохраненная в объекте, которую мы условно называем vptr. Как это можно осуществить, если эта дополнительная информация не будет сохранена в Base?

Ну и главное, данный сценарий порождает неопределенное поведение. Что будет дальше, не знает никто! Вот так и нужно было ответить.

P.S. В простейшей реализации виртуального механизма, которую можно себе представить, на любую из таблиц виртуальных функций могут одновременно ссылаться множество объектов. Эти объекты появляются и исчезают, появляются и исчезают, а таблица остается в памяти неизменной. Когда освободится память занимаемая таблицей? Опять же, достоверно это знает только компилятор, но вероятно, при завершении программы. И память занимаемую таблицей будет освобождать код, сгенерированный компилятором (если освобождение вообще требуется как таковое). Так что даже если при освобождении какого-то из объектов произошла утечка памяти. то это вряд ли занимаемая виртуальной таблицей. Ну и повторюсь, после того, как программа породила UB, все дальнейшие прогнозы того, что произойдет дальше просто некорректно.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 10.04.2023 20:51 rg45 . Предыдущая версия . Еще …
Отредактировано 10.04.2023 20:49 rg45 . Предыдущая версия .
Отредактировано 10.04.2023 20:42 rg45 . Предыдущая версия .
Отредактировано 10.04.2023 20:41 rg45 . Предыдущая версия .
Отредактировано 10.04.2023 20:30 rg45 . Предыдущая версия .
Re: Как удаляется vptr?
От: cppguard  
Дата: 11.04.23 02:24
Оценка: +1
Здравствуйте, avovana, Вы писали:

A>Привет с собеседования в тинькове.


Я бы забородил тебя на собеседовании лишь за неумение выразить простую мысль нормальным языком. vptr не может никуда утекать, это статический массив. Вероятно, вопрос был, по классике, про виртуальный деструктор. И либо вы с собеседователем оба говорите на инопланетянском, либо ты не понял вопрос.
Отредактировано 11.04.2023 2:29 cppguard . Предыдущая версия .
Re[4]: Как удаляется vptr?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 11.04.23 04:04
Оценка:
Здравствуйте, rg45, Вы писали:

R>Да, на уровне идеи это можно представлять себе примерно так. Нужно только понимать, что ни сам vptr, ни таблица виртуальных функций, на которую он указывает, не доступны программисту. Эти структуры данных полностью управляются компилятором, и то, как они устроены, где располагаются, в какой момент и в какой области выделяется память под таблицы виртуальных функций и в какой момент эта память освобождается — об этом знает только компилятор и в разных компиляторах это может быть устроено по-разному.


По факту, как минимум под винду, все делают одинаково, иначе бы COM сломался бы
Маньяк Робокряк колесит по городу
Re: Как удаляется vptr?
От: paradok  
Дата: 11.04.23 07:08
Оценка:
Здравствуйте, avovana, Вы писали:


A>int main(void) {

A> Base* base = new Derived;
base->>basePrint();
A> delete base;
A> return 0;
A>}

а в реальности у вас наблюдается утечка или нет?
Re[2]: Как удаляется vptr?
От: avovana Россия  
Дата: 11.04.23 08:08
Оценка:
Здравствуйте, cppguard, Вы писали:

C>... vptr не может никуда утекать, это статический массив. Вероятно, вопрос был, по классике, про виртуальный деструктор. И либо вы с собеседователем оба говорите на инопланетянском, либо ты не понял вопрос.

1) Вопрос был и по классике.
2) И был вопрос про "утечёт ли vptr Derived'а если delete base; И деструктор базового класса не виртуальный.". Какой бы вы дали ответ? Это максимальный контекст, который у вас есть от интервьювера. Дальше ваши размышления. И от того как вы ответите, напротив этого вопроса он либо поставит вам галочку, либо нет. Так, что? Утечёт? vptr же член derived класса?
Отредактировано 11.04.2023 8:21 avovana . Предыдущая версия . Еще …
Отредактировано 11.04.2023 8:20 avovana . Предыдущая версия .
Re[4]: Как удаляется vptr?
От: avovana Россия  
Дата: 11.04.23 08:17
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, avovana, Вы писали:


A>>То есть правильно здесь представили что vptr лишь у базового. И наследники как-будто бы его наследуют?


R>Да, на уровне идеи это можно представлять себе примерно так. Нужно только понимать, что ни сам vptr, ни таблица виртуальных функций, на которую он указывает, не доступны программисту. Эти структуры данных полностью управляются компилятором, и то, как они устроены, где располагаются, в какой момент и в какой области выделяется память под таблицы виртуальных функций и в какой момент эта память освобождается — об этом знает только компилятор и в разных компиляторах это может быть устроено по-разному.


Отлично разъяснили, спасибо.
Теперь ответьте, пожалуйста, дорогому интервьюеру:

"Где находится vptr у созданного объекта. И утечёт ли он, если деструктор базового класса невиртуальный?"
int main(void) { 
    Base* base = new Derived; 
    base->basePrint(); 
    delete base; 
    return 0; 
}

На 1ый вопрос, как понял, вы уже ответили — что это компилятор-specific. И что, в принципе, согласны, что может быть реализация, что vptr один для всех. И может хранится в базовом классе. И на какую таблицу вирт методов он указывает зависит от того какие конструкции сделал компилятор и как ими пользуется программа в run-time имея тип текущего this на руках. Тогда на 2ой логично ответить, что поскольку vptr — член базового класса, то ничего страшного в delete base не произойдёт? Он "не утечёт"?
Отредактировано 11.04.2023 8:19 avovana . Предыдущая версия .
Re[4]: Как удаляется vptr?
От: avovana Россия  
Дата: 11.04.23 08:24
Оценка:
Здравствуйте, Marty, Вы писали:

M>Ничего не понял, опять сумбур какой-то

Вот с таким сумбуром про утечёт ли vptr я и столкнулся

M>Вообще интересно. А куда стукнуть? Я б тоже сходил. В крайнем случае — принесу ещё ржаки на форум

Чуть позже в личку скину. Классно, если окажется ржака в стиле — "вот это были задачки, прошёл"
Re[3]: Как удаляется vptr?
От: cppguard  
Дата: 11.04.23 08:24
Оценка:
Здравствуйте, avovana, Вы писали:

A>2) И был вопрос про "утечёт ли vptr Derived'а если delete base;". Какой бы вы дали ответ? Это максимальный контекст, который у вас есть от интервьювера. Дальше ваши размышления. И от того как вы ответите, напротив этого вопроса он либо поставит вам галочку, либо нет. Так, что? Утечёт?


Если прямо вот такой дословный вопрос, то я бы собрался и ушёл с собеседования. Опыт говорит, что даже за большие деньги с мудаками лучше не работать — нервы потом лечить дороже выйдет. На всякий случай ещё раз повторюсь — vptr то статический массив, а в экземпляре класса хранится указатель на него. Перефразируя Матроскина: чтобы что-то утекло, нужно сначало что-то выделить.
Re[3]: Как удаляется vptr?
От: SaZ  
Дата: 11.04.23 08:38
Оценка: +1
Здравствуйте, avovana, Вы писали:

A>Здравствуйте, cppguard, Вы писали:


C>>... vptr не может никуда утекать, это статический массив. Вероятно, вопрос был, по классике, про виртуальный деструктор. И либо вы с собеседователем оба говорите на инопланетянском, либо ты не понял вопрос.

A>1) Вопрос был и по классике.
A>2) И был вопрос про "утечёт ли vptr Derived'а если delete base; И деструктор базового класса не виртуальный.". Какой бы вы дали ответ? Это максимальный контекст, который у вас есть от интервьювера. Дальше ваши размышления. И от того как вы ответите, напротив этого вопроса он либо поставит вам галочку, либо нет. Так, что? Утечёт? vptr же член derived класса?

Никуда ничего не утечёт. Стандартом не регламентировано, но одно из возможных решений такое:
1. Выделить кусок памяти размером sizeof(vptr) + sizeof(VashClass)
2. Проинициализировать vptr
3. Вернуть указатель на память, увеличенный на sizeof(vptr)

Таким образом указатель на таблицу будет лежать по отрицательному смещению и к нему легко достучаться. Но при освобождении памяти всё корректно удалится, блок памяти то целостный и компилятор будет знать о факте наличия этого самого vptr по типу базового класса.
Re[4]: Как удаляется vptr?
От: avovana Россия  
Дата: 11.04.23 09:19
Оценка:
Здравствуйте, cppguard, Вы писали:

C>Здравствуйте, avovana, Вы писали:


A>>2) И был вопрос про "утечёт ли vptr Derived'а если delete base;". Какой бы вы дали ответ? Это максимальный контекст, который у вас есть от интервьювера. Дальше ваши размышления. И от того как вы ответите, напротив этого вопроса он либо поставит вам галочку, либо нет. Так, что? Утечёт?


C>Если прямо вот такой дословный вопрос, то я бы собрался и ушёл с собеседования. Опыт говорит, что даже за большие деньги с мудаками лучше не работать — нервы потом лечить дороже выйдет. На всякий случай ещё раз повторюсь — vptr то статический массив, а в экземпляре класса хранится указатель на него. Перефразируя Матроскина: чтобы что-то утекло, нужно сначало что-то выделить.


Прощу прощения из-за возможного недопонимания. Возможно, надо было более ясно термины прописать. Под vptr имел ввиду virtual pointer. Вы, наверное, имеете ввиду саму таблицу на которую этот pointer указывает? Если говорите про статический массив.
Вот именно про этот virtual pointer, добавляемый компилятором объекту созданного класса и невидимый для программиста, и идёт речь.
Re[4]: Как удаляется vptr?
От: avovana Россия  
Дата: 11.04.23 09:23
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Здравствуйте, avovana, Вы писали:


A>>Здравствуйте, cppguard, Вы писали:


C>>>... vptr не может никуда утекать, это статический массив. Вероятно, вопрос был, по классике, про виртуальный деструктор. И либо вы с собеседователем оба говорите на инопланетянском, либо ты не понял вопрос.

A>>1) Вопрос был и по классике.
A>>2) И был вопрос про "утечёт ли vptr Derived'а если delete base; И деструктор базового класса не виртуальный.". Какой бы вы дали ответ? Это максимальный контекст, который у вас есть от интервьювера. Дальше ваши размышления. И от того как вы ответите, напротив этого вопроса он либо поставит вам галочку, либо нет. Так, что? Утечёт? vptr же член derived класса?

SaZ>Никуда ничего не утечёт. Стандартом не регламентировано, но одно из возможных решений такое:

SaZ>1. Выделить кусок памяти размером sizeof(vptr) + sizeof(VashClass)
SaZ>2. Проинициализировать vptr
SaZ>3. Вернуть указатель на память, увеличенный на sizeof(vptr)

SaZ>Таким образом указатель на таблицу будет лежать по отрицательному смещению и к нему легко достучаться. Но при освобождении памяти всё корректно удалится, блок памяти то целостный и компилятор будет знать о факте наличия этого самого vptr по типу базового класса.


И тогда, получается, не важно виртуальный ли деструктор у базового класса. Когда будем удалять этот объект — delete base будет знать об этом header'e(с виртуальным указателем) лежащим левее/выше и спокойно его удалит?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.