2015-08-18 4 views
1

Я нахожу это раздражающим, что я могу вызвать неконстантные функции объекта, если у меня есть указатель на этот объект. Я не могу позволить указателю быть указателем const, потому что есть также неконстантные функции, которые мне нужно вызвать. Поэтому мой единственный вариант, похоже, делает static_casts, чтобы гарантировать, что константа также работает по указателям. Вот минимальный пример:Что такое static_cast накладные расходы при добавлении константы при сохранении того же типа?

class MyClassImpl 
{ 
    MyClassImpl(void) : m_i(0) {} 

    int increment(void) { 
    ++m_i; 
    return m_i; 
    } 

    private: 
    int m_i; 
}; 

class MyClass 
{ 
    MyClass(void) : m_pImpl(new MyClassImpl()){} 

    ~MyClass(void) { 
    delete m_pImpl; 
    } 

    int doNothing(void) const { 
    m_pImpl->increment(); // works although MyClassImpl::increment() is non-const 
    // static_cast<const MyClassImpl *>(m_pImpl)->increment(); // this will not compile because of non-constness 
    } 


    private: 
    MyClass(const MyClass & rhs); 
    MyClassImpl * m_pImpl; 
}; 

Однако, мне интересно, имеет ли static_cast какие-либо затраты во время выполнения. Полностью оцениваются static_casts во время компиляции или есть некоторые накладные расходы, предполагая, что doNothing() вызывается часто.

Редактировать: Мой вопрос отличается от C++ static_cast runtime overhead, потому что в моем случае static_cast добавляет только константу. Другие пользователи, которые могут найти этот вопрос, могут быть заинтересованы в указанном вопросе.

+0

Накладные расходы зависят от типов. Если вы только добавляете const, то нет накладных расходов. –

+0

Почему 'static_cast' вместо' const_cast'? – nwp

+0

@nwp: static_cast может добавлять константу, но не удалять ее. Const_cast может удалить константу. Следовательно, static_cast более безопасен. – Fabian

ответ

2

Накладные расходы времени выполнения - это, по сути, копия указателя, которая может быть полностью оптимизирована.

Но в вашем случае, я бы рассмотреть вопрос об изменении int m_i; к mutable std::atomic<int> m_i; и сделать increment константу в базовом классе тоже. Это похоже на счетчик ссылок, и мой способ позволяет (i) сохранить const -корректность и (ii) быть потокобезопасным. Я также рассмотрю возможность изменения int на unsigned, чтобы избежать неопределенного поведения, если m_i становится слишком большим.

+1

Зачем копировать указатель? В этом случае изменяется только 'const'-qualification, поэтому, скорее всего, это не-op. – Quentin

+1

Действительно, компилятор может оптимизировать временный. Но это не хуже, чем копия указателя. – Bathsheba