Я хочу реализовать Подкачку () метод для моего класса (давайте назовем это A) сделать оператор копии-и-подкачки = (). Насколько я знаю, подкачиваю метод, должен быть реализован путем свопинга всех членов класса, например:
class A
{
public:
void swap(A& rhv)
{
std::swap(x, rhv.x);
std::swap(y, rhv.y);
std::swap(z, rhv.z);
}
private:
int x,y,z;
};
Но что я должен сделать, если у меня есть участник константы? Я не могу назвать станд.:: подкачка для него, таким образом, я не могу кодировать A:: Подкачка ().
Править: На самом деле мой класс немного более сложен. Я хочу Сериализировать и Десериализовать его. Участник константы является частью данных, которые не изменятся (его идентификатор, например) в этом объекте. Таким образом, я думал о записи чего-то как:
class A
{
public:
void Serialize(FILE* file) const
{
fwrite(&read_a, 1, sizeof(read_a), file);
}
void Deserialize(FILE* file) const
{
size_t read_a;
fread(&read_a, 1, sizeof(read_a), file);
A tmp(read_a);
this->Swap(tmp);
}
private:
const size_t a;
};
и вызов этот код:
A a;
FILE* f = fopen(...);
a.Deserialize(f);
Я сожалею о такой неопределенной формулировке.
Я думаю, что фраза обычно используется для обозначения цикла, который повторяется много раз, и который может оказать серьезное влияние на производительность программы - то есть он может использовать много циклов ЦП. Обычно вы слышите эту фразу в обсуждении оптимизации.
Например, я думаю об играх, где цикл может потребовать обработки каждого пикселя на экране, или научном приложении, где цикл обрабатывает записи в гигантских массивах точек данных.
-121--937652-Есть хороший пример плотной петли (~ бесконечный цикл) в видео Джон Скит и Тони Пони .
Пример:
while(text.IndexOf(" ") != -1) text = text.Replace(" ", " ");
, который создает плотный цикл, поскольку IndexOf
игнорирует символ нулевой ширины Юникода (таким образом, находит два смежных космический), но Replace
не игнорирует их (таким образом, не заменяя ни один смежный космический).
В других ответах уже есть хорошие определения, поэтому больше я их не упоминаю.
-121--937653-После хороших ночей сна я думаю, что лучший ответ - использовать не-const указатель на значение const - после всего этого семантика, которую вы пытаетесь захватить.
Я предлагаю вам использовать указатели на экземпляры. Указатели можно поменять местами намного проще, чем данные в классе
или структуре
.
Единственный способ поменять местами постоянное значение - это создать другой объект или клонировать
текущий объект.
Дана структура:
struct My_Struct
{
const unsigned int ID;
std::string name;
My_Struct(unsigned int new_id)
: ID(new_id)
{ ; }
};
Насколько я понимаю, вы хотите поменять местами экземпляры чего-то вроде My_Struct
выше. Вы можете скопировать изменяемые (неконстантные) члены, но не член const
. Единственный способ изменить член const
- создать новый экземпляр с новым значением для члена const
.
Возможно, вам нужно переосмыслить свой дизайн.
f0b0s, хороший принцип проектирования - проектировать объекты так, чтобы они были неизменяемыми . Это означает, что объект не может измениться после создания. Чтобы «изменить» объект, вы должны скопировать объект и обязательно изменить нужные вам элементы.
При этом, в этом случае вам следует использовать конструктор копирования вместо копирования объектов, которые вы хотите поменять местами, а затем фактически поменять местами ссылки на объект. Я понимаю, что было бы заманчиво просто изменить элементы объекта под капотом, но было бы лучше сделать копию объекта и заменить ссылки на этот объект на NEW вместо этого. Это избавит вас от любых неприятностей.
Надеюсь, это поможет.
ВАЖНО подумать о том, чтобы не менять членов CONST.
PD: Я думаю, вы могли бы подумать об использовании рефлексии в вашем подходе. так что вам не придется поддерживать функцию.
Я думаю, что вам действительно нужно иметь внутреннюю структуру данных, которой можно легко обмениваться между объектами. Например:
class A
{
private:
struct A_Data {
int x;
int y;
const int z;
A_Data(int initial_z) : z(initial_z) {}
};
std::auto_ptr<A_Data> p_data;
public:
A(int initial_z) : p_data(new A_Data(initial_z)) {}
void swap(A& rhv) {
std::swap(p_data, rhv.p_data);
}
};
Это сохраняет значение z
постоянным в любом экземпляре внутренних данных объекта A
, но вы можете поменять местами внутренние данные двух объектов A
(включая значение константы z
) без нарушения константной корректности.
Именно поэтому был создан const_cast
. Просто не забывайте не отстреливать ногу.
Редактирование: Хорошо, я уступаю - const_cast вообще не был создан для этой проблемы. Это может сработать с вашим компилятором, но вы не можете на это рассчитывать, и если демоны вылетают из ноздрей, пожалуйста, не вините меня.