Как я могу заставить созданный компилятор Copy Constructor из класса To * не включен компилятором?

StackOverflow https://stackoverflow.com/questions/3870538

Вопрос

Заголовок альтернативного вопроса:Как явно иметь Commiler Generate Code для созданных компиляторов конструкторов в конкретном блоке перевода?

Проблема, которую мы сталкиваемся, это то, что для одного кода путь в результате - тщательно измерено - производительность лучше (на 5%), если копирование-CTOR вызывает один объект нет Универсан, то есть если этот конструктор реализован вручную. (Мы заметили это, потому что во время очистки кода излишне явно реализованный CTOR CTOR этого класса (17 членов) был удален.)

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

Сейчас мы сталкиваемся с выбором просто брошения ручного кода COPOR-CTOR обратно (он делает точно так же, как компилятор, созданный один) или нахождение каких-либо других средств нет Включение копии CTOR этого класса.

Есть ли какие-либо средства (для Microsoft Visual C ++), чтобы явно создали функции класса Contage C ++), созданные компиляторы, созданные классы в определенном устройстве перевода или будут ли они всегда включены в каждом блоке перевода, где они используются? (Комментарии для GCC или других компиляторов также могут получить лучшее изображение ситуации.)


С первых 2 ответов показывают некоторое недоразумение: Компилятор сгенерирован Классные функции генерируются только самими компилятором, если они не объявлены, и не определены пользователем. Поэтому не могут быть применены модификаторы, поскольку эти функции не существует в Sourcecode.

struct A {
  std::string member;
};

A Имеет CTOR CTOR, DTOR и оператор копирования. Ни одна из этих функций не может быть изменена через некоторые DELUSPEC, потому что они не существуют в коде.

struct B {
  std::string member;
  B(B const& rhs);
};

B Теперь есть А. Подобный пользователь Копировать CTOR и пользователь должен его реализовать. Компилятор не будет генерировать код для него.


Еще немного фона для сомнений :-) ...

Этот код скомпилирован с использованием MS Visual C ++, но это связано для встроенной (-подобной) (Realtime) системы. Производительность была измерена путем принятия времени на эту систему, и поэтому я думаю, что ребята, которые взяли сроки, будут иметь приличные номера.

Тест проводился путем сравнения двух версий кода, где Только Разница была встроенным против Not-Inline Copy Ctor из этого класса. Время с включенным кодом было хуже примерно на 5%.


Дальнейшая проверка показала, что я ошибился в одной точке: компилятор буду Создайте отдельные функции для сложных конструкторов копирования. Это сделает это по своему усмотрению, и это также зависит от настроек оптимизации. Таким образом, в нашем случае компилятор делает неправильную вещь в наших конкретных обстоятельствах. Из ответов до сих пор это не появляется, мы можем сказать компилятору иначе. :-(

Это было полезно?

Решение 6

Чтобы добавить свой собственный вывод и ответить на точный вопрос, не входя в детали:

  1. Ты не можем сила Компилятор, в частности VC ++, для встроенного или не входит в систему сгенерированного компилятора CTOR / DTOR / ITC. - но

  2. Оптимизатор выберет - по своему усмотрению - если он включает в себя код для созданной функции компилятора (CTOR) или, если она генерирует функцию «REAL» для этого кода. AFAIK Нет никакого способа повлиять на решение оптимизатора в этом отношении.

Другие советы

$ 12,1 / 5- 5- "неявно заявленный конструктор по умолчанию - это встроенный государственный член его класса.".

Так что мы ничего не можем сделать. Конструктор Improcit должен быть встроенным. Любое другое поведение в этом отношении, вероятно, будет продолжением

Было сказано, что,

Вполне вероятно, что ваш ручной конструктор копирования (который вы удалили во время очистки кода), делали правильные вещи. В качестве примера, если один из членов (из 17) в вашем классе является элементом указателя, вполне вероятно, что конструктор ручной копирования позаботился о глубокой копии (и, следовательно, принял удар производительности).

Итак, если вы не вниматенно просмотрите ваш ручной конструктор копирования, даже не думайте об удалении его и полагаться на (потенциально багги) неявным конструктором копирования (в вашем контексте)

Я очень сомневаюсь, что есть что-то отношение к этому. Если компилятор включает в себя сгенерированный компилятор CTOR CTOR, почему бы он также не встроен в явном определенном определении? (Также необычно, что оптимизация компилятора Euristics не работает так плохо, как сделать свернутый код 5% медленнее)

Перед прыжками на выводы,

  • Проверьте генерируемую сборку, чтобы убедиться, что две версии фактически выполняют то же самое (и в том же порядке, используя одну и ту же сборку и так далее, так как иначе это может быть источником вашей разности производительности)
  • Убедитесь, что сгенерировал компилятор на самом деле является Быть навязчивым и определенным вручную нет.

Если это так, не могли бы вы обновить свой вопрос с этой информацией?

В C ++ нет способа указывать, должна ли функция сгенерированной компилятора или не должна быть включена. Даже не специфичные для поставщиков расширений, такие как __declspec(noinline) Поможет вам там, так как вы явно передаете всю ответственность за функцию для компилятора. Таким образом, компилятор выбирает, что делать с этим, как это реализовать и ли его встроить. Вы не можете сказать, что «Пожалуйста, реализуйте эту функцию для меня», и в то же время «Пожалуйста, позвольте мне контролировать, как выполняется функция». Если вы хотите контролировать функцию, вы должны реализовать его. ;)

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

Но опять же, я не убежден, что встраивание это проблема. Скорее всего, две функции просто приводят к образованию различного монтажа.

__declspec (Noinline).

Документация говорит, что она применяется только к функциям-членам, но на самом деле он работает с бесплатными функциями.

Часто лучше изолировать его до нескольких основных типов, которые вы знаете, проблематичны. Пример A:

class t_std_string {
    std::string d_string;
public:
    /* ... */

    /* defined explicitly, and out of line -- you know what to do here */
    t_std_string();
    t_std_string(const std::string& other);
    t_std_string(const t_std_string& other);
    ~t_std_string();

    inline std::string& get() { return this->d_string; }
    inline const std::string& get() const { return this->d_string; }
    /* ... */
};

struct B {
    t_std_string member;
    /* 16 more */
    /* ... */
};

Или вы можете занять его бесплатно. Пример B:

/* B.hpp */

struct B {
private:

    /* class types */
    struct t_data {
        std::string member;

        /* 16 more ... */
    public:
        /* declare + implement the ctor B needs */

        /* since it is otherwise inaccessible, it will only hurt build times to make default ctor/dtor implicit (or by implementing them in the header, of course), so define these explicitly in the cpp file */
        t_data();
        ~t_data();

        /* allow implicit copy ctor and assign -- this could hurt your build times, however. it depends on the complexity/visibility of the implementation of the data and the number of TUs in which this interface is visible. since only one object needs this... it's wasteful in large systems */
    };
private:

    /* class data */
    t_data d_data;
public:
    /* you'll often want the next 4 out of line
       -- it depends on how this is created/copied/destroyed in the wild
     */
    B();
    B(const B& other);
    ~B();
    B& operator=(const B&);
};

/* B.cpp */

/* assuming these have been implemented properly for t_data */
B::B() : d_data() {
}

B::B(const B& other) : d_data(other) {
}

B::~B() {
}

B& B::operator=(const B&) {
    /* assuming the default behaviour is correct...*/
    this->d_data = other.d_data;
    return *this;
}
/* continue to B::t_data definitions */

Вы можете использовать какой-то вложенный объект. Таким образом, конструктор копирования вложенного объекта может быть оставлен в качестве не требующей технического обслуживания по умолчанию, но у вас все еще есть явно созданный конструктор копирования, который вы можете объявить Noinline.

class some_object_wrapper {
    original_object obj;
    __declspec(noinline) some_object_wrapper(const some_object_wrapper& ref) 
        : obj(ref) {}
    // Other function accesses and such here
};

Если вы отчаянные, вы можете скомпилировать рассматриваемый класс отдельно в .lib и ссылку на него. Изменение его на другой блок перевода не остановится VC ++ из встроенного его. Кроме того, я должен вопрос о том, на самом деле они делают то же самое. Почему вы реализовали механизм ручной копирования, если он делает то же самое, что и для конструктора копирования по умолчанию?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top