C ++ объект пользовательского типа, возвращаемый в регистр процессора. Как работают методы экземпляров? - PullRequest
1 голос
/ 19 марта 2019

Я знаю, что когда я вызываю метод экземпляра, адрес объекта присваивается параметру «this» скрытого указателя.Таким образом, метод может получить доступ к переменным экземпляра текущего объекта, в отличие от статических методов, не имеющих этого параметра и поэтому не может ссылаться на текущий экземпляр.

Поэтому мой вопрос:

Когда небольшой объект возвращается в регистр ЦП (обычно в регистр RAX), так как объект не имеет адреса, потому что его нет в памяти,

  • Как может метод экземплярассылка на объект?

  • что происходит с параметром «const this»?

в этом случае нет доступных адресов.

Ответы [ 3 ]

1 голос
/ 19 марта 2019

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

Обычно в c ++ любое ненаблюдаемое поведениеможно оптимизировать далеко.Не видя определения функции, компилятор не может знать, как используется указатель this, и должен поместить объект в адресуемую память.

См. Этот пример https://gcc.godbolt.org/z/Zff5nr, где объект возвращается в регистр eax,хранится в стеке, и его адрес передается в регистре rdi функции-члену.

0 голосов
/ 20 марта 2019

Это вопрос для компилятора, а не для программиста.Язык требует, чтобы указатель this был доступен в методах экземпляра.Если оптимизирующий компилятор решает, что он может выполнить требование, и все еще сохраняет все в регистрах, ему разрешается делать это согласно правилу , как если бы : внутренняя часть реализации не имеет значения, если obervable *Поведение 1005 * такое же, как если бы машина выполняла строго по стандарту (без оптимизации).

Поэтому, если вы не нацелены на конкретный компилятор с конкретными параметрами компиляции, на этот вопрос невозможно ответить.

Например, давайте посмотрим как следующий код:

#include <iostream>
#include <iomanip>

class Foo {
    int val;

public:
    Foo(int val = 0): val(val) {}

    friend std::ostream& operator << (std::ostream& out, const Foo& f);
};

std::ostream& operator << (std::ostream& out, const Foo& f) {
    out << std::hex << std::setw(2) << f.val;
    return out;
}

int main() {
    for (int i=0; i<10; i++) {
        std::cout << Foo(i);
    }
    std::cout << std::endl;
    return 0;
}

Компилятор может легко сделать вывод, что это программа с одним модулем компиляции: она содержит main и не использует внешних ссылок вне стандартной библиотеки.И что он просто возобновляет:

#include <iostream>
#include <iomanip>

int main() {
    for (int i=0; i<10; i++) {
        std::cout << std::hex << std::setw(2) << i;
    }
    std::cout << std::endl;
    return 0;
}

Оптимизация всего определения класса и друга operator <<.

Очень умный компьютер может даже догадываться, что, поскольку 10 является константойexpr, все может быть разрешено во время компиляции и может генерировать тот же код, что и:

#include <iostream>

int main() {
    std::cout << " 0 1 2 3 4 5 6 7 8 9\n";
    return 0;
}

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

0 голосов
/ 19 марта 2019

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

Не следует думать слишком буквальноо языковых конструкциях при сравнении их с кодом, который фактически генерируется.Например, указатель this может вообще не существовать как указатель, если вызываемый вами метод фактически был встроен компилятором.Что касается const this, constness - это понятие чисто во время компиляции, которое только помогает компилятору решить, какую оптимизацию он может выполнить, однако он никоим образом не применяется во время выполнения.

...