powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / что делает оператов присваивания в моем коде?
64 сообщений из 64, показаны все 3 страниц
что делает оператов присваивания в моем коде?
    #38098914
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет!
У меня есть класс Person
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
class Person
{
public:
	char *Name;
	char PhoneNumber[21];

	Person()
	{
		Name = new char[1];
		strcpy(Name,"\0");
		strcpy(PhoneNumber,"");
	}

	Person(char Name[], char PhoneNumber[])
	{
		this->Name = new char[strlen(Name)+1];
		strcpy(this->Name,Name);
		strcpy(this->PhoneNumber,PhoneNumber);
	}

	~Person()
	{
		delete [] Name;
	}
};


Оператор присваивание не объявлен явно, но я читал, что он все равно создается компилятором. В основном коде я создаю 3 объекта, а потом по одному записываю их в массив.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
int main()
{
	setlocale(LC_ALL, "RUS");

	//создал объекты
	Person obj1("Neil", "+380677777771");
	Person obj2("Joe", "+380677777772");
	Person obj3("Leonora", "+380677777773");

	Person * Source = new Person[3]; //вот здесь создалось 3 новых объекта с использованием конструктора по умолчанию
	
        Source[1] = obj1; //вот что происходит здесь?

	system("Pause");
	return 0;
}


Вот в этой строчке кода, я так понимаю, задействуется конструктор присваивания?
Код: plaintext
1.
Source[1] = obj1;


И мне очень интересно, как копируется динамическое поле Name. Ведь в изначальном объекте под это поле было выделена всего одна ячейка char, а в obj1 аж целых пять. Что происходит в конструкторе присваивания? Старая выделенная память (1 байт) удаляется и создается новый массив char на 5 элементов?
Я так понимаю, это очень важно понять, потому что я могу здесь потерять память или получить ошибку, когда деструктор попробует удалить уже удаленный кусок памяти.
Заранее спасибо!
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38098915
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GВедь в изначальном объекте под это поле было выделена всего одна ячейка
char
Нет. В любом объекте это поле - указатель. Поскольку ты его объявил как указатель. Почитай
об указателях, на пальцах это трудно объяснять.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38098918
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovMaximuS_GВедь в изначальном объекте под это поле было выделена всего одна ячейка
char
Нет. В любом объекте это поле - указатель. Поскольку ты его объявил как указатель. Почитай
об указателях, на пальцах это трудно объяснять.

Сорри, я путаюсь в том, как правильно сформулировать вопрос. Я имел ввиду что этот указатель указаывает на массив из одной ячейки, и когда после операции присваивания, этот указатель указывает на массив из 5ти ячеек. А что случилось с памятью выделенной под массив из одной ячейки?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38098922
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GА что случилось с памятью выделенной под массив из одной ячейки?

Что случается с цифрой на часах, когда ты переводишь стрелку, которая на неё указывает?
Ничего. Абсолютно ничего. Она по прежнему выделена, но теперь никто не знает где она.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38098936
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GИ мне очень интересно, как копируется динамическое поле Name. Ведь в изначальном объекте под это поле было выделена всего одна ячейка char, а в obj1 аж целых пять. Что происходит в конструкторе присваивания? Старая выделенная память (1 байт) удаляется и создается новый массив char на 5 элементов?Нет, кусок памяти в один байт останется существовать, но никто более не знает где он находится поэтому и освободить его уже невозможно. Это потеря памяти в чистом виде.

MaximuS_GЯ так понимаю, это очень важно понять, потому что я могу здесь потерять память или получить ошибку, когда деструктор попробует удалить уже удаленный кусок памяти.Нет, сообщения об ошибке ты не получишь. Деструктор удалит кусок памяти в пять байт, а про однобайтовый кусок все просто забыли.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38098940
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov , White Owl
Я Вас понял, спасибо большое! Значит сейчас буду пробовать прикручивать конструктор присваивания, который удалит эту одну ячейку.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38098949
Edd.Dragon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_G Dimitry Sibiryakov , White Owl
Я Вас понял, спасибо большое! Значит сейчас буду пробовать прикручивать конструктор присваивания, который удалит эту одну ячейку.
Вы лучше подумайте, что дальше будете делать. Когда у вас два, три, N объектов будут указывать на одну и ту же память, которую все дружно попытаются при разружшении удалить N раз.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38098950
Edd.Dragon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну точнее, будут пытаться, если вы просто скопируете указатель при присвоении
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38098958
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Edd.DragonMaximuS_G Dimitry Sibiryakov , White Owl
Я Вас понял, спасибо большое! Значит сейчас буду пробовать прикручивать конструктор присваивания, который удалит эту одну ячейку.
Вы лучше подумайте, что дальше будете делать. Когда у вас два, три, N объектов будут указывать на одну и ту же память, которую все дружно попытаются при разружшении удалить N раз.
Не совсем понимаю, почему объекты будут указывать на одну и ту же память? У них у каждого своя. А в конструкторе присваивания я использую метод strcpy, а не буду копировать указатели. Что я упускаю?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38098961
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот, добавил конструктор присваивания:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
class Person
{
	...
	Person& operator=(const Person& from)
	{
		char *temp = this->Name;
		delete [] temp;
		this->Name = new char[strlen(from.Name)+1];
		strcpy(this->Name,from.Name);
		return *this;
	}
	...
}
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099017
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_G, это не конструктор, а оператор присваивания. и обязательно делай проверку на присваивание самому себе, т.е.:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
class Person
{
	...
	Person& operator=(const Person& from)
	{
		if( this == &from ) return *this;

		char *temp = this->Name;
		delete [] temp;
		this->Name = new char[strlen(from.Name)+1];
		strcpy(this->Name,from.Name);
		return *this;
	}
	...
}
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099024
не бывает
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximuS_GВот, добавил конструктор присваивания:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
class Person
{
	...
	Person& operator=(const Person& from)
	{
		char *temp = this->Name;
		delete [] temp;
		this->Name = new char[strlen(from.Name)+1];
		strcpy(this->Name,from.Name);
		return *this;
	}
	...
}


Конструктора присваивания не бывает.
Есть:
1. конструктор копирования
2. оператор присваивания

Имеют место в следующих случаях:
Код: plaintext
1.
2.
3.
4.
T a = 1; // параметризированный конструктор
T b(a);  // конструктор копирования 
T c = a; // конструктор копирования 
c = a; // оператор присваивания
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099034
Edd.Dragon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GА в конструкторе присваивания я использую метод strcpy
Тогда норм. Просто скопировать не догадываются чаще чем освободить. Копируют указатель.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099036
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychMaximuS_G, это не конструктор, а оператор присваивания. и обязательно делай проверку на присваивание самому себе, т.е.:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
class Person
{
	...
	Person& operator=(const Person& from)
	{
		if( this == &from ) return *this;

		char *temp = this->Name;
		delete [] temp;
		this->Name = new char[strlen(from.Name)+1];
		strcpy(this->Name,from.Name);
		return *this;
	}
	...
}


Спасибо за совет! Я даже не джумал, что кто-то может сам себе присвоить :). Это типа проверка на такое:
Код: plaintext
1.
2.
3.
4.
5.
6.
//создал объекты
	Person obj1("Neil", "+380677777771");
	Person obj2("Joe", "+380677777772");
	Person obj3("Leonora", "+380677777773");

       obj1=obj1;


?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099038
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не бываетMaximuS_GВот, добавил конструктор присваивания:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
class Person
{
	...
	Person& operator=(const Person& from)
	{
		char *temp = this->Name;
		delete [] temp;
		this->Name = new char[strlen(from.Name)+1];
		strcpy(this->Name,from.Name);
		return *this;
	}
	...
}


Конструктора присваивания не бывает.
Есть:
1. конструктор копирования
2. оператор присваивания

Имеют место в следующих случаях:
Код: plaintext
1.
2.
3.
4.
T a = 1; // параметризированный конструктор
T b(a);  // конструктор копирования 
T c = a; // конструктор копирования 
c = a; // оператор присваивания


Спасибо за подсказку! Я вот такой конструкции не встречал
T a = 1;
Это тоже самое что
T a(1)
?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099041
MaximuS_Gне бываетпропущено...

Конструктора присваивания не бывает.
Есть:
1. конструктор копирования
2. оператор присваивания

Имеют место в следующих случаях:
Код: plaintext
1.
2.
3.
4.
T a = 1; // параметризированный конструктор
T b(a);  // конструктор копирования 
T c = a; // конструктор копирования 
c = a; // оператор присваивания


Спасибо за подсказку! Я вот такой конструкции не встречал
T a = 1;
Это тоже самое что
T a(1)
?
Да. Везде конструктор копирования.
T a = 1; эквивалентно T a(1);

T b;
T a = b; эквивалентно T a(b);
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099042
эквивалентноT a = 1; эквивалентно T a(1);

Точнее здесь параметризированный конструктор.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099056
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GЯ даже не джумал, что кто-то может сам себе присвоить :). Это типа проверка на такое:
Код: plaintext
1.
2.
3.
4.
5.
6.
//создал объекты
	Person obj1("Neil", "+380677777771");
	Person obj2("Joe", "+380677777772");
	Person obj3("Leonora", "+380677777773");

       obj1=obj1;


?скорее, на такое:
Код: plaintext
1.
2.
3.
4.
Person obj( ... );
Person *p1 = &obj;  // ( 1 )
Person *p2 = &obj;  // ( 2 )
*p1 = *p2; // ( 3 )

если строки ( 1 ) и ( 2 ) далеко разнесены друг от друга в коде, то вероятность появления строки ( 3 ) довольно высока. В любом случае, это очень простой способ избавить себя от возможных проблем, вроде как помыть руки перед едой.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099169
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychMaximuS_GЯ даже не джумал, что кто-то может сам себе присвоить :). Это типа проверка на такое:
Код: plaintext
1.
2.
3.
4.
5.
6.
//создал объекты
	Person obj1("Neil", "+380677777771");
	Person obj2("Joe", "+380677777772");
	Person obj3("Leonora", "+380677777773");

       obj1=obj1;


?скорее, на такое:
Код: plaintext
1.
2.
3.
4.
Person obj( ... );
Person *p1 = &obj;  // ( 1 )
Person *p2 = &obj;  // ( 2 )
*p1 = *p2; // ( 3 )

если строки ( 1 ) и ( 2 ) далеко разнесены друг от друга в коде, то вероятность появления строки ( 3 ) довольно высока. В любом случае, это очень простой способ избавить себя от возможных проблем, вроде как помыть руки перед едой.
Спасибо большое! Добавил в оператор присваивания :)
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099182
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
эквивалентноMaximuS_Gпропущено...

Спасибо за подсказку! Я вот такой конструкции не встречал
T a = 1;
Это тоже самое что
T a(1)
?
Да. Везде конструктор копирования.
T a = 1; эквивалентно T a(1);

T b;
T a = b; эквивалентно T a(b);
Я понял, спасибо большое!
Вот таким образом
Код: plaintext
1.
T a = 1;


я так понял можно инициализировать объект, если в параметризированном конструкторе один параметр. А если несколько параметров, можно как-то через равно инициализировать объект? Вот так, как со структурой, не получается.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
struct my
{
	int a;
	int b;
};

my ob = {1,1};


Заранее спасибо!
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099215
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И еще вопрос появился. Вот здесь я читаю про конструкторы, и автор приводит такой пример:
Рассмотрим простой класс:
Код: plaintext
1.
2.
3.
4.
5.
6.
class Message
{
private:
	unsigned Id_;
	std::string Text_;
};


При его создании компилятор автоматически создаст конструктор по умолчанию в котором будет вызван конструктор по умолчанию для каждого из членов, но только если член не является встроенным типом (int, double и т.д.) и деструктор:
Код: plaintext
1.
2.
3.
4.
Message()
	: Text_()
{
}


Я не могу понять как это так записано - Message() потом двоеточие, а потом Text_() . Подскажите, пожалуйста.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099250
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Edd.DragonПросто скопировать не догадываются чаще чем освободить. Копируют
указатель.
Или заботятся о быстродействии. В таких случаях используют умные указатели, счётчики
ссылок или флаг владельца.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099412
Dimitry SibiryakovEdd.DragonПросто скопировать не догадываются чаще чем освободить. Копируют
указатель.
Или заботятся о быстродействии. В таких случаях используют умные указатели, счётчики
ссылок или флаг владельца.

А в каком умном указателе используется флаг владельца и чем он лучше счетчика ссылок?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099415
MaximuS_GИ еще вопрос появился. Вот здесь я читаю про конструкторы, и автор приводит такой пример:
Рассмотрим простой класс:
Код: plaintext
1.
2.
3.
4.
5.
6.
class Message
{
private:
	unsigned Id_;
	std::string Text_;
};


При его создании компилятор автоматически создаст конструктор по умолчанию в котором будет вызван конструктор по умолчанию для каждого из членов, но только если член не является встроенным типом (int, double и т.д.) и деструктор:
Код: plaintext
1.
2.
3.
4.
Message()
	: Text_()
{
}


Я не могу понять как это так записано - Message() потом двоеточие, а потом Text_() . Подскажите, пожалуйста.
То что идет после имени конструктора после двоеточия - это список инициализации. В нем можно вызывать конструкторы членов класса.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
class Message
{
Message()
	: Text_("a")  // конструктор копирования
{
	Text_ = "b"; // оператор присваивания
}

private:
	unsigned Id_;
	std::string Text_;
};



Аналог без класса:
Код: plaintext
1.
2.
std::string Text_("a");
Text_ = "b";
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099497
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
флаг владельцаА в каком умном указателе используется флаг владельца и чем он лучше
счетчика ссылок?
В моём собственном. Не требует ссылки на структуру.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099591
покажете
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakovфлаг владельцаА в каком умном указателе используется флаг владельца и чем он лучше
счетчика ссылок?
В моём собственном. Не требует ссылки на структуру.

А не покажете его, когда там флаг устанавливается и как копирование происходит?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099634
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
список инициализацииТо что идет после имени конструктора после двоеточия - это список инициализации. В нем можно вызывать конструкторы членов класса.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
class Message
{
Message()
	: Text_("a")  // конструктор копирования
{
	Text_ = "b"; // оператор присваивания
}

private:
	unsigned Id_;
	std::string Text_;
};



Аналог без класса:
Код: plaintext
1.
2.
std::string Text_("a");
Text_ = "b";



Спасибо за комментарий. То есть это можно так инициализировать поля класса с помощью конструктора класса? Не совсем понимаю, зачем это надо...
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099645
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
покажетекогда там флаг устанавливается и как копирование происходит?

В copy-конструкторе, натурально. И копирование происходит с помощью оператора присваивания.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099650
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

А зачем нужен этот смартуказатель с флагом владельца?
Почему нельзя применить простой указатель когда нет владения, и какой-нибудь unique_ptr для владения?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099651
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyПочему нельзя применить простой указатель когда нет владения, и
какой-нибудь unique_ptr для владения?
Затем, что право владения у меня переходящее и мне было проще изобрести собственный
велосипед чем ковыряться в STL.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099653
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakovправо владения у меня переходящее
Мне просто хотелось обеспечить работоспособность кода
Код: sql
1.
throw MyException("Invalid value %d", v);


без лишних операций с динамической памятью и копированием её содержимого.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099659
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

Допустим (хотя auto_ptr/unique_ptr как раз и реализуют передачу владения - не знаю зачем ковыряться в STL чтобы это узнать).
Но наличие обертки над указателем, без гарантии что указатель еще валидный, создает ложное ощущение что управление автоматическое, хотя по сути контроль за валидностью указателя по прежнему лежит на программисте.
Т.е. состояние когда флаг владения не установлен - бессмысленно. Сам указатель должен быть таким флагом, а при передаче владения - обнуляться.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099668
Dimitry SibiryakovDimitry Sibiryakovправо владения у меня переходящее
Мне просто хотелось обеспечить работоспособность кода
Код: sql
1.
throw MyException("Invalid value %d", v);


без лишних операций с динамической памятью и копированием её содержимого.

А где тут могут возникнуть проблемы с динамической памятью?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099678
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyСам указатель должен быть таким флагом, а при передаче владения -
обнуляться.
Да, это было бы логично если бы я был уверен, что "старый" экземпляр уже не будет
использоваться после создания нового. Возможно, при следующей чистке кода я так и сделаю.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099686
Mozok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychMaximuS_G, это не конструктор, а оператор присваивания. и обязательно делай проверку на присваивание самому
ИМХО, согласен в этом плане с товарищем Саттером, который говорит,
что наличие таких проверок зачастую озаначает просчет в архитектуре.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
	Person& operator=(const Person& from)
	{
		char *temp = new char[strlen(from.Name)+1];
                strcpy(temp,from.Name);
		delete [] this->Name;
		this->Name = temp;
		
		return *this;
	}


И никаких проверок не нужно.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099696
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MozokegorychMaximuS_G, это не конструктор, а оператор присваивания. и обязательно делай проверку на присваивание самому
ИМХО, согласен в этом плане с товарищем Саттером, который говорит,
что наличие таких проверок зачастую озаначает просчет в архитектуре.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
	Person& operator=(const Person& from)
	{
		char *temp = new char[strlen(from.Name)+1];
                strcpy(temp,from.Name);
		delete [] this->Name;
		this->Name = temp;
		
		return *this;
	}


И никаких проверок не нужно.
Но в Вашем случае произойдет копирование данных, а в случае с проверкой - нет. Эти конструкторы по разному реагируют на присваивание одного и того же объекта друг другу. Или я не прав?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099703
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mozok,

Лучше (хоть по сути и то же самое) реализовать метод swap(T&) и тогда оператор копирования (как и swap) будет выглядеть тривиально (а значит менее подвержен ошибкам, в т.ч. из-за дублирования кода конструктора копирования):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
	Person& operator=(const Person& from)
	{
		Person temp = from;
		swap(temp);
		return *this;
	}
	void swap(Person& other)
	{
	 	std::swap(Name, other.Name);
	}	
	


Таким образом останется реализовать только конструктор копирования, а не дублировать его логику в оператор.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099705
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GНо в Вашем случае произойдет копирование данных, а в случае с проверкой - нет. Эти конструкторы по разному реагируют на присваивание одного и того же объекта друг другу. Или я не прав?
Прав.
Но присвоение в себя - это ошибка кодирования.
В норме ее не должно быть.
А заниматься оптимизацией кода, который редко исполняется - это пустая трата ресурсов.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099713
Anatoly MoskovskyMozok,

Лучше (хоть по сути и то же самое) реализовать метод swap(T&) и тогда оператор копирования (как и swap) будет выглядеть тривиально (а значит менее подвержен ошибкам, в т.ч. из-за дублирования кода конструктора копирования):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
	Person& operator=(const Person& from)
	{
		Person temp = from;
		swap(temp);
		return *this;
	}
	void swap(Person& other)
	{
	 	std::swap(Name, other.Name);
	}	
	


Таким образом останется реализовать только конструктор копирования, а не дублировать его логику в оператор.
Но при изменениях класса придется менять и void swap и конструктор копирования?

Либо наоборот :)
Код: plaintext
1.
2.
3.
4.
	Person(const Person& from)
	{
		*this = from;
	}


Останется реализовать только оператор = с глубоким копированием. При изменении класса придется менять только его.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099715
Anatoly MoskovskyMaximuS_GНо в Вашем случае произойдет копирование данных, а в случае с проверкой - нет. Эти конструкторы по разному реагируют на присваивание одного и того же объекта друг другу. Или я не прав?
Прав.
Но присвоение в себя - это ошибка кодирования.
В норме ее не должно быть.
А заниматься оптимизацией кода, который редко исполняется - это пустая трата ресурсов.
А присвоение в себя в данном случае можно как-то отловить во время компиляции?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099720
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyMaximuS_GНо в Вашем случае произойдет копирование данных, а в случае с проверкой - нет. Эти конструкторы по разному реагируют на присваивание одного и того же объекта друг другу. Или я не прав?
Прав.
Но присвоение в себя - это ошибка кодирования.
В норме ее не должно быть.
А заниматься оптимизацией кода, который редко исполняется - это пустая трата ресурсов.
Тогда я запутался, лучше делать проверку, или нет? :)
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099733
Edd.Dragon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyНо присвоение в себя - это ошибка кодирования.

Ой ли?

Мания компактного кода заставляет каждого второго писать что-то типа
Код: plaintext
1.
b = (a > b ? a : b)



Но кто сказал, что это ошибка кодирования? Можно долго спорить о философской стороне вопроса. Но практическая сторона однозначно заявляет, что такой код совершенно корректен и не безсмысленен абсолютно, чтобы однозначно назвать его говонокодом.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099736
Edd.Dragon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GТогда я запутался, лучше делать проверку, или нет? :)
Делайте, делайте. При разработке универсальных контейнеров динамических данных лишняя проверка лишней не бывает. А для глубокой оптимизации сложных алгоритмов, работающих с динамическими данными нужно выбрасывать к чертям все эти универсальные контейнеры и писать велосипеды, реализующие алгоритм и структуры данных строго под задачу. В противном случае хоть с этой проверкой, хоть без нее при интенсивном использовании динамических строк, массивов и производных от них типов столько лишних телодвижений происходит, что эта проверка - капля в море. Но если таким путем достигаются иные выгоды, то и ладно.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099739
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Edd.DragonMaximuS_GТогда я запутался, лучше делать проверку, или нет? :)
Делайте, делайте. При разработке универсальных контейнеров динамических данных лишняя проверка лишней не бывает. А для глубокой оптимизации сложных алгоритмов, работающих с динамическими данными нужно выбрасывать к чертям все эти универсальные контейнеры и писать велосипеды, реализующие алгоритм и структуры данных строго под задачу. В противном случае хоть с этой проверкой, хоть без нее при интенсивном использовании динамических строк, массивов и производных от них типов столько лишних телодвижений происходит, что эта проверка - капля в море. Но если таким путем достигаются иные выгоды, то и ладно.
Ясно, спасибо! :)
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099777
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Либо наоборотЛибо наоборот :)
Код: plaintext
1.
2.
3.
4.
	Person(const Person& from)
	{
		*this = from;
	}


Останется реализовать только оператор = с глубоким копированием. При изменении класса придется менять только его.
Нельзя вызывать присвоение для еще несконструированного объекта с мусором в полях.
Сначала надо создать валидный эземпляр.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099784
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Edd.DragonAnatoly MoskovskyНо присвоение в себя - это ошибка кодирования.

Ой ли?

Мания компактного кода заставляет каждого второго писать что-то типа
Код: plaintext
1.
b = (a > b ? a : b)



А где тут компактность?
Если уж компактно записывать то вот так (на 1 символ короче) :)
Код: plaintext
1.
if (a > b) b = a;


Но кто сказал, что это ошибка кодирования? Можно долго спорить о философской стороне вопроса. Но практическая сторона однозначно заявляет, что такой код совершенно корректен и не безсмысленен абсолютно, чтобы однозначно назвать его говонокодом.
Конечно это говнокод. Именно такой код получается когда стоит задача написать компактно, а не понятно.

Конкретно по проверке на присвоение в себя - эту проверку можно делать только для оптимизации.
Если без нее код присвоения работает неверно - то это неверная реализация присвоения.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099795
возможно?
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyЛибо наоборотЛибо наоборот :)
Код: plaintext
1.
2.
3.
4.
	Person(const Person& from)
	{
		*this = from;
	}


Останется реализовать только оператор = с глубоким копированием. При изменении класса придется менять только его.
Нельзя вызывать присвоение для еще несконструированного объекта с мусором в полях.
Сначала надо создать валидный эземпляр.
Все члены класса к этому моменту проинициализированы дефолтными значениями. За исключением тех у кого нет конструктора без параметров - их придется писать в списке инициализации.

А как возможно?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
struct Person {
int a, b, c;
	Person(const Person& from)
	{
		a = from.a;    // 1. возможно?
		this->b = from.b; // 2.  возможно?
		*this = from; // 3. возможно?
	}
};
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099800
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
возможно?,

Это все возможно в некоторых частных случаях.
И будет работать до первого рефакторинга, когда один частный случай перейдет в другой.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099812
Anatoly Moskovskyвозможно?,

Это все возможно в некоторых частных случаях.
И будет работать до первого рефакторинга, когда один частный случай перейдет в другой.
Приведите пример когда это не будет работать?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099821
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Приведите примерAnatoly Moskovskyвозможно?,

Это все возможно в некоторых частных случаях.
И будет работать до первого рефакторинга, когда один частный случай перейдет в другой.
Приведите пример когда это не будет работать?
Например, почленное копирование из константной ссылки непотокобезопасно, т.к. неатомарно.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099825
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, вы ж просили пример, когда не работает. Вот он:
Либо наоборот
Код: plaintext
1.
2.
3.
4.
	Person(const Person& from)
	{
		*this = from;
	}
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099830
Т.е. тут
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
struct Person {
int a, b, c;
	Person(const Person& from)
	{
		a = from.a;    // 1. возможно?
		this->b = from.b; // 2.  возможно?
		*this = from; // 3. возможно?
	}
};


Anatoly Moskovskyвсе возможно в некоторых частных случаях.
а тут уже
Anatoly Moskovskyне работает:
Либо наоборот
Код: plaintext
1.
2.
3.
4.
	Person(const Person& from)
	{
		*this = from;
	}




Anatoly MoskovskyПриведите примерпропущено...

Приведите пример когда это не будет работать?
Например, почленное копирование из константной ссылки непотокобезопасно, т.к. неатомарно.
Ну так та же самая проблема и в вашем примере:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
	Person& operator=(const Person& from)
	{
		Person temp = from;
		swap(temp);
		return *this;
	}
	void swap(Person& other)
	{
	 	std::swap(Name, other.Name);
	}	
	
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38099833
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
та же самая проблема Т.е. тут все возможно в некоторых частных случаях а тут уже не работает

Пример, с *this = from - не работает для реального класса рассмотренного в данном топике, где есть поле Name. А с вашими int конечно будет работать. Но вы же не думаете что вам так всегда будет везти?
Ведь пока я вам не указал на необходимость инициализации полей перед вызовом присвоения, вы и не вспомнили об этом, хотя уверен, что знали. Т.е. в реальном проекте когда дело дошло бы до подобного кода, вполне вероятно вы бы тоже забыли.

та же самая проблема
Anatoly Moskovsky
Например, почленное копирование из константной ссылки непотокобезопасно, т.к. неатомарно.
Ну так та же самая проблема и в вашем примере:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
	Person& operator=(const Person& from)
	{
		Person temp = from;
		swap(temp);
		return *this;
	}
	void swap(Person& other)
	{
	 	std::swap(Name, other.Name);
	}	
	


А где вы в этом примере видете почленное копирование из внешнего объекта?
Или вы предполагаете что я бы криво написал конструктор копирования, который здесь не приведен?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100029
Anatoly Moskovskyта же самая проблема Т.е. тут все возможно в некоторых частных случаях а тут уже не работает

Пример, с *this = from - не работает для реального класса рассмотренного в данном топике, где есть поле Name. А с вашими int конечно будет работать. Но вы же не думаете что вам так всегда будет везти?
Ведь пока я вам не указал на необходимость инициализации полей перед вызовом присвоения, вы и не вспомнили об этом, хотя уверен, что знали. Т.е. в реальном проекте когда дело дошло бы до подобного кода, вполне вероятно вы бы тоже забыли.
Я же писал, поля инициализируются конструктором по умолчанию сами - помнить не надо. А у кого нет такого конструктора, там компилятор подскажет - тоже помнить не надо.

Anatoly Moskovskyта же самая проблемапропущено...

Ну так та же самая проблема и в вашем примере:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
	Person& operator=(const Person& from)
	{
		Person temp = from;
		swap(temp);
		return *this;
	}
	void swap(Person& other)
	{
	 	std::swap(Name, other.Name);
	}	
	


А где вы в этом примере видете почленное копирование из внешнего объекта?
Или вы предполагаете что я бы криво написал конструктор копирования, который здесь не приведен?
Нет, это вы предполагаете, что я бы криво написал оператор присваивания, который у меня не приведен.
Вы просто читали очень не внимательно и подумали, что я оставлю operator= по умолчанию, по этому у вас и какие-то проблемы с Name, многопоточностью и т.д.
Либо наоборот
Код: plaintext
1.
2.
3.
4.
	Person(const Person& from)
	{
		*this = from;
	}


Останется реализовать только оператор = с глубоким копированием . При изменении класса придется менять только его.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100045
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
читали очень не внимательноAnatoly Moskovskyпропущено...

Пример, с *this = from - не работает для реального класса рассмотренного в данном топике, где есть поле Name. А с вашими int конечно будет работать. Но вы же не думаете что вам так всегда будет везти?
Ведь пока я вам не указал на необходимость инициализации полей перед вызовом присвоения, вы и не вспомнили об этом, хотя уверен, что знали. Т.е. в реальном проекте когда дело дошло бы до подобного кода, вполне вероятно вы бы тоже забыли.
Я же писал, поля инициализируются конструктором по умолчанию сами - помнить не надо. А у кого нет такого конструктора, там компилятор подскажет - тоже помнить не надо.

Поле Name это указатель. У него нет и не может быть никаких конструкторов.
При входе в конструктор копирования там мусор, который в вашем операторе присвоения будет рассматриваться как адрес блока памяти который нужно освободить перед установкой нового значения.
И никакие известные мне компиляторы ничего не подсказывают в такой ситуации - такой анализ замедлил бы компиляцию, так как предполагает поиск пути в графах.

Таким образом, перед вызовом присвоения в к-торе копирования все равно нужно проинициализировать корректно каждое поле, и никакого преимущества в минимизации дублирования перенос логики копирования в оператор= не дает. Зато сложность кода растет, т.к. теперь конструктор и оператор зависят друг от друга.
В случае же когда логика находится в к-торе + swap, то только оператор= зависит от к-тора, а метод swap тривиален (он вообще в большинстве случаев может быть реализован как побитный swap всего объекта, без перечисления отдельных полей, а в остальных случаях - просто линейный регулярный код)
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100049
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
читали очень не внимательноНет, это вы предполагаете, что я бы криво написал оператор присваивания, который у меня не приведен.
Вы просто читали очень не внимательно и подумали, что я оставлю operator= по умолчанию, по этому у вас и какие-то проблемы с Name, многопоточностью и т.д.

Причем здесь корректность оператора=?
Я вам указал на проблему в конкретном коде конструктора, где перед вызовом = копируете два поля из from.
Это неатомарное действие, чья неатомарность не зависит от корректности кода =.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100090
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот тут обсуждаются эти два подхода и их достоинства и недостатки:
http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
http://stackoverflow.com/questions/3652103/implementing-the-copy-constructor-in-terms-of-operator

Краткое резюме: никаких достоинств у подхода реализующего конструктор копирования через оператор= нет. Зато недостатков полно.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100116
Anatoly Moskovskyчитали очень не внимательнопропущено...

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

Поле Name это указатель. У него нет и не может быть никаких конструкторов.
При входе в конструктор копирования там мусор, который в вашем операторе присвоения будет рассматриваться как адрес блока памяти который нужно освободить перед установкой нового значения.
И никакие известные мне компиляторы ничего не подсказывают в такой ситуации - такой анализ замедлил бы компиляцию, так как предполагает поиск пути в графах.

Таким образом, перед вызовом присвоения в к-торе копирования все равно нужно проинициализировать корректно каждое поле, и никакого преимущества в минимизации дублирования перенос логики копирования в оператор= не дает. Зато сложность кода растет, т.к. теперь конструктор и оператор зависят друг от друга.
В случае же когда логика находится в к-торе + swap, то только оператор= зависит от к-тора, а метод swap тривиален (он вообще в большинстве случаев может быть реализован как побитный swap всего объекта, без перечисления отдельных полей, а в остальных случаях - просто линейный регулярный код)
Теперь понятно что вы имели ввиду.
Да, в случае динамического выделения памяти никакой пользы от моего подхода не будет. Естественно нужно будет указатели инициализировать NULL.
Но в любом случае в operator= делается проверка на NULL перед освобождением памяти и только затем выделение.
Хотя, не знаете, по стандарту указатели по умолчанию не инициализируются NULL/null_ptr?

Но если это не жизненно необходимо, лучше использовать умные указатели и контейнеры вместо обычных указателей для динамической памяти.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100120
Anatoly Moskovskyчитали очень не внимательноНет, это вы предполагаете, что я бы криво написал оператор присваивания, который у меня не приведен.
Вы просто читали очень не внимательно и подумали, что я оставлю operator= по умолчанию, по этому у вас и какие-то проблемы с Name, многопоточностью и т.д.

Причем здесь корректность оператора=?
Я вам указал на проблему в конкретном коде конструктора, где перед вызовом = копируете два поля из from.
Это неатомарное действие, чья неатомарность не зависит от корректности кода =.
Я привел примеры почленного копирования в конструкторе только, чтобы понять что вы имели ввиду.
Естественно предполагалось, что вариант operator= потокобезопасный.
Сейчас почитаю что там на stackoverflow пишут.

Кстати, std::swap по стандарту атомарный?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100148
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
умные указатели и контейнерыХотя, не знаете, по стандарту указатели по умолчанию не инициализируются NULL/null_ptr?
По умолчанию не инициализируются, как и другие POD-члены без конструкторов.
Хотя в некоторых случаях (например когда у контейнера вообще нет пользовательских конструкторов) неявная инициализация членов нулями производится при явной инициализации контейнера через к-тор по умолчанию (T t = T()). Но к конструктору копирования это не относится.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100153
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
operator= потокобезопасныйКстати, std::swap по стандарту атомарный?
Нет. Но это обычно и не требуется.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100503
Mozok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GТогда я запутался, лучше делать проверку, или нет? :)
Разве что ассертом, так будет лучше всего. Потому что
Anatoly MoskovskyНо присвоение в себя - это ошибка кодирования.
В норме ее не должно быть.
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100605
static_assert
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MozokMaximuS_GТогда я запутался, лучше делать проверку, или нет? :)
Разве что ассертом, так будет лучше всего. Потому что
Anatoly MoskovskyНо присвоение в себя - это ошибка кодирования.
В норме ее не должно быть.

А static_assert'ом это можно как-то отловить?
...
Рейтинг: 0 / 0
что делает оператов присваивания в моем коде?
    #38100617
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
При компиляции нельзя определить.

Но я вообще думаю, что это не такая серьезная ошибка, чтобы ее наказывать ассертом.
И иногда при несильно продуманной архитектуре (а это почти любая архитектура ) такие ситуации неизбежны
Думаю падение скорости достаточное наказание :)
...
Рейтинг: 0 / 0
64 сообщений из 64, показаны все 3 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / что делает оператов присваивания в моем коде?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]