Ограничения реализации ключевого слова this в C ++, так как оно относится к опасному, но функциональному примеру - PullRequest
0 голосов
/ 21 сентября 2018

Я знаю, что значение данного this не может быть определено во время компиляции.Мне остается только удивляться, что после того, как данный объект выделен и создан, кэшируется ли значение this, или существует ли буквальная оценка выражения при каждом использовании?Вот конкретный пример, который мотивирует мой вопрос.Имейте в виду, что это нарушает все доктрины ООП и функции защиты, которые С ++ стремится поддерживать.

int main()
{
    string s1 = string("I am super a super long string named s1, and won't be SSO");
    string s2 = string("I am super a super long string named s2, and won't be SSO");

    byte* s1interface = reinterpret_cast<byte*>(&s1);
    byte* s2interface = reinterpret_cast<byte*>(&s2);

    static_assert(sizeof s1 == sizeof s2);

    for(int offset(0); offset < sizeof s1; ++offset)
    {
        *(s1interface + offset) ^= *(s2interface + offset);
        *(s2interface + offset) ^= *(s1interface + offset);
        *(s1interface + offset) ^= *(s2interface + offset);
    }

    cout << s1 << '\n' << s2 << "\n\n\n";

    return 0;
}
//outputs:
//I am super a super long string **named s2**, and won't be SSO
//I am super a super long string **named s1**, and won't be SSO
//(The emphasis on the output strings was added by me to highlight the identity change)

Я хочу начать с того, что эта программа не только компилирует, но и вырабатывает этот вывод последовательно.Мой вопрос не основан на том, почему / как это работает.

На мой взгляд, любые внутренние переменные, даже те, которые управляют динамической памятью, будут трансплантированы, как только объекты будут (ре) правильно сформированы.,Тем не менее, я предполагаю гипотетический сценарий, в котором this запрашивается объектом и затем сохраняется внутри.После операции по пересадке объекта &me не будет совпадать с this, который был запрошен и сохранен при первоначальной конструкции, что серьезно повредило бы любые операции, использующие this, в сочетании с любым отражением адреса времени выполнения.Хотя это никогда не должно делаться, и все ставки не принимаются, если кто-то осмелится сделать что-либо настолько отвратительное с любым их объектом или иным образом, предписывает ли Стандарт постоянную оценку this или просто для this, чтобы выполнить то, что он говорит в соответствии спредположение, что объект будет занимать только место, где он помещен?

РЕДАКТИРОВАТЬ: Позвольте мне объяснить это по-другому, если во время выполнения объект имеет скрытый и внутренний this, который записывается после его выделенияи все последующие чтения this считывают сохраненное значение, после того, как &object и this пересадки не будут одинаковыми.Это явно не так, как это реализовано моим компилятором, но я хочу знать, является ли это соответствием или удачей.

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Поэтому я обратился к Стефану Лававежу ( на сайте Стефана ), который поддерживает реализацию Стандартной библиотеки для Microsoft, с этим вопросом.Я опубликую его ответ ниже.Я хочу отметить, что пользователь HAL9000 был по существу прав в своем ответе, но, поскольку Стефан был очень тщательным, я опубликую его и в конечном итоге обозначу его как официальный ответ ( труднополучить более официальный, чем слова кого-то, кто на самом деле поддерживает реализацию стандарта Big 3 ).Если вы найдете этот ответ информативным, ответ HAL9000 содержит наглядный пример, подтверждающий эту идею.

Слова Стефана:

Не следует думать, что указатель "this" хранитсявнутри объекта.Ментальная модель неявных параметров является наиболее точной.Когда функция x () вызывает функцию-член Meow :: y () для объекта Meow m, x () уже должна знать адрес m.Это может быть локальная переменная (x () знает, где все ее локальные переменные находятся в стеке), это может быть указатель с разыменованной ссылкой (если m равен * ptr, ptr указывает на m), он может передаваться через ссылку (ссылкине являются указателями, но они фактически имеют ту же информацию о местоположении, что и указатели), это может быть элемент массива (если m - это arr [idx], тогда arr + idx указывает на m) и т. д. Итак, Meow :: y () будет неявно передан адрес m, который становится «this» внутри функции-члена.

Важно, если у вас есть структура, которая содержит простые старые данные (например, кучу целых), и вы меняете содержимоеиз двух структур объекты не изменяют идентичность - только их содержание.Если я возьму все ваши вещи в вашем доме и обменяю их на вещи в чужом доме, расположение домов не изменится.(В C ++ объекты не могут мигрировать с одного адреса памяти на другой - самое большее, что вы можете сделать, это создать отдельный объект, переместить все вещи, сказать всем, кому небезразлично старое местоположение, вместо этого указать новое местоположение, а затемуничтожить пустую оболочку исходного объекта - это, по сути, семантика перемещения.)

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

Надеюсь, это поможет, STL

0 голосов
/ 21 сентября 2018

Значение this никогда не "запрашивается" объектом.Он передается (нестатическим) объектным методам как неявный параметр.

Предположим, у вас есть этот код C ++:

#include <stdio.h>

class mystring
{
public:
   char *data;  
   void print();
};

void mystring::print() 
{
   fputs(this->data, stdout);
}

void
main()
{
   mystring s = {"Hello World"};  

   s.print();
}

Теперь похоже, что метод print не принимает никаких параметров, но фактически это указатель на объект s,Таким образом, компилятор сгенерирует код, эквивалентный этой программе на c.

#include <stdio.h>

struct mystring
{
   char *data;  
};

void mystring_print(struct mystring *this) 
{
   fputs(this->data, stdout);
}

void
main()
{
   mystring s = {"Hello World"};  

   mystring_print(&s);
}

Так что с указателем this нет ничего волшебного.Это просто скучный параметр, как и любой другой.С виртуальными методами дела обстоят немного интереснее, но обработка this остается прежней

...