Сколько и как используется «const» в C ++?

«Как только деструктор вызывается для объекта, объект больше не существует, поведение не определено, если деструктор вызывается для объекта, срок жизни которого закончился»

blockquote>

Проект стандарта C ++ §12.4.12

Как отмечают другие, это не означает, что реализация всегда будет делать что-то явно нежелательное (например, ошибка сегментации). Это означает, что он может делать все, что наиболее удобно.

121
задан BradleyDotNET 16 September 2014 в 21:37
поделиться

3 ответа

Попытка собрать некоторое использование:

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

ScopeGuard const& guard = MakeGuard(&cleanUpFunction);

Объяснение , с помощью кода:

struct ScopeGuard { 
    ~ScopeGuard() { } // not virtual
};

template<typename T> struct Derived : ScopeGuard { 
    T t; 
    Derived(T t):t(t) { }
    ~Derived() {
        t(); // call function
    }
};

template<typename T> Derived<T> MakeGuard(T t) { return Derived<T>(t); }

Этот прием используется в классе утилиты ScopeGuard Alexandrescu. После того как временный файл выходит из объема, деструктор Полученных называют правильно. Вышеупомянутый код пропускает некоторые маленькие детали, но это - грандиозное предприятие с ним.

<час>

константа Использования для сообщения методов других не изменит логическое состояние этого объекта.

struct SmartPtr {
    int getCopies() const { return mCopiesMade; }
};
<час>

константа Использования для классов копии на записи , чтобы заставить компилятор помочь Вам решить, когда и если не необходимо скопировать.

struct MyString {
    char * getData() { /* copy: caller might write */ return mData; }
    char const* getData() const { return mData; }
};

Объяснение : Вы могли бы хотеть обменяться данными при копировании чего-то, пока данные первоначально и объект copie'd остаются тем же. После того как один из объекта изменяет данные, Вам однако нужны теперь две версии: Один для оригинала, и один для копии. Таким образом, Вы копия на запись к любому объекту, так, чтобы они теперь у обоих была их собственная версия.

использующий код :

int main() {
    string const a = "1234";
    string const b = a;
    // outputs the same address for COW strings
    cout << (void*)&a[0] << ", " << (void*)&b[0];
}

вышеупомянутый отрывок печатает тот же адрес на моем GCC, потому что пользовавшаяся библиотека C++ реализует копию на записи std::string. Обе строки, даже при том, что они - отдельные объекты, совместно используют ту же память для своих строковых данных. Создание b неконстанта предпочтет версию неконстанты operator[], и GCC создаст копию буфера резервной памяти, потому что мы могли изменить его, и это не должно влиять на данные [1 112]!

int main() {
    string const a = "1234";
    string b = a;
    // outputs different addresses!
    cout << (void*)&a[0] << ", " << (void*)&b[0];
}
<час>

, Чтобы конструктор копии сделал копии с объектов константы и временных файлов :

struct MyClass {
    MyClass(MyClass const& that) { /* make copy of that */ }
};
<час>

Для того, чтобы сделать константы, которые тривиально не могут измениться

double const PI = 3.1415;
<час>

Для передачи произвольных объектов ссылкой вместо значением - для предотвращения возможно дорогой или невозможной передачи значением

void PrintIt(Object const& obj) {
    // ...
}
97
ответ дан Johannes Schaub - litb 16 September 2014 в 21:37
поделиться

Существует действительно 2 основного использования константы в C++.

значения Константы

, Если значение в форме переменной, участника или параметра, который не будет (или не должен) быть измененными в течение его времени жизни необходимо отметить его константа. Это помогает предотвратить мутации на объекте. Например, в следующей функции я не должен изменяться, Студенческий экземпляр передал так, я отмечаю его константа

void PrintStudent(const Student& student) {
  cout << student.GetName();
}

относительно того, почему Вы сделали бы это. Намного легче рассуждать об алгоритме, если Вы знаете, что базовые данные не могут измениться. "константа" помогает, но не гарантирует, что это будет достигнуто.

, Очевидно, печатая данные в суд не требует очень мысли :)

отмечание членского метода как константа

В предыдущем примере, я отметил Студента как константу, Но как C++ знал, что, называя GetName () метод на студенте не видоизменит объект? Ответ - то, что метод был отмечен как константа

class Student {
  public:
    string GetName() const { ... }
};

, отмечание метода "константа" делает 2 вещи. Прежде всего, это говорит C++, что этот метод не видоизменит мой объект. Вторая вещь состоит в том, что все членские переменные будут теперь рассматривать, как будто они были отмечены как константа. Это помогает, но не препятствует тому, чтобы Вы изменили экземпляр своего класса.

Это - чрезвычайно простой пример, но надо надеяться он поможет ответить на Ваши вопросы.

26
ответ дан pyrrhic 16 September 2014 в 21:37
поделиться
  • 1
    Это точно что we' ре, планирующее прямо сейчас, с теми же выравниваниями. – Jim T 29 October 2009 в 17:32

Заботьтесь для понимания различия между этими 4 объявлениями:

следующие 2 объявления идентичны семантически. Можно измениться , где ccp1 и точка ccp2, но Вы не можете изменить вещь, на которую они указывают.

const char* ccp1;
char const* ccp2;

Затем, указатель является константой, так чтобы быть значимым это должно быть инициализировано для указания на что-то. Вы не можете заставить его указать на что-то еще, однако вещь, на которую это указывает на , может быть измененной.

char* const cpc = &something_possibly_not_const;

Наконец, мы комбинируем два - таким образом, указываемая вещь не может быть изменена, и указатель не может указать на больше нигде.

const char* const ccpc = &const_obj;

по часовой стрелке правило на спирали может помочь распутать объявление http://c-faq.com/decl/spiral.anderson.html

15
ответ дан Steve Folly 16 September 2014 в 21:37
поделиться
  • 1
    Я соглашаюсь с supermagic' s подход. Думайте с точки зрения общих библиотек, а не совместно использованного codefiles/projects. Добавьте скомпилированный двоичный файл для общей библиотеки к Вашему проекту. Этот подход имеет тот же эффект как включая внешний облик к тегу, но ни одной из головных болей обслуживания из-за руководящего внешнего облика. Некоторые проблемы I' опытные ve создают тег с внешним обликом к соединительной линии и соединительной линии и ответвлению, указывающему на внешнее то же. По-моему, риски внешнего облика перевешивают свои преимущества. – mcdon 4 September 2010 в 05:39
Другие вопросы по тегам:

Похожие вопросы: