Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.12.2013, 16:33   #1
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию Конструктор прсвоения класса, использующего new

Почему не могу использовать
MyClass instA = someFunction()
или
MyClass instA = instB?

Ведь string st = retStr() прекрасно работает.
Код:
#include <string>
#include <iostream>

class ClsA{
public:
	ClsA(char * s)
	{
		if ( !s || strlen(s) == 0)
		{
			sizeDat = 0;
			dat = nullptr;
			return;
		}
		sizeDat = strlen(s)+1;
		dat = new char[sizeDat];
		std::memcpy(dat, s, sizeDat);
	}
	~ClsA(){
		if (dat)
			delete[] dat;
	}
	ClsA &operator=(ClsA & clsAssgn){
		if (dat)
			delete[] dat;
		dat =new char[clsAssgn.sizeDat];
		std::memcpy(this->dat, clsAssgn.dat, clsAssgn.sizeDat);
			return *this;
	}
	ClsA &operator=(char * s){
		if (dat)
			delete[] dat;
		
		if (strlen(s) == 0)
		{
			sizeDat = 0;
			dat = nullptr;
		}
		
		sizeDat = strlen(s) +1;
		dat = new char[sizeDat];
		std::memcpy(dat, s, sizeDat);
		return *this;
	}
	char * GetDat(){
		return dat;
	}
protected:
	char * dat;
	int sizeDat;
};

ClsA ret(){
	ClsA a("sample");
	return a;
}
using namespace std;

int main(int argc, char* argv[])
{
	ClsA a("sample");
	
	ClsA g("");
	g = a;          // вот тут operator= вызывается
	cout << g.GetDat() << endl;
	string st = string("copy string");

	cout << st << std::endl;
	cout << g.GetDat() << endl;

	ClsA b = ret();          // вот тут operator= ничерта не вызывается

	cout << b.GetDat() << endl; // exception! :(((
	getchar();
	return 0;
}
Визуал Студио, есличе

Последний раз редактировалось Smogg; 03.12.2013 в 16:53.
Smogg вне форума Ответить с цитированием
Старый 03.12.2013, 17:25   #2
Ezhik Kihze
Форумчанин
 
Регистрация: 24.12.2012
Сообщений: 639
По умолчанию

Вы не возвращайте локальный стековый объект для начала.
ICQ: 677936656 Gmail: ekEmbed@gmail.com
Ezhik Kihze вне форума Ответить с цитированием
Старый 03.12.2013, 17:38   #3
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

Цитата:
Сообщение от Ezhik Kihze Посмотреть сообщение
Вы не возвращайте локальный стековый объект для начала.
А есть разница? Стд::стринги ж нормально возвращаются.

Сейчас у меня возвращается указатель на статичный объект, у которого есть перегруженный оператор=:
ClsA operator=(ClsA * instAssgn);
Но, блин, также есть и ClsA operator=(ClsA instAssgn);

Это некрасиво, когда один и тот же оператор работает как с объектами, так и с указателями на оные...

Отчего вместо аккуратного
Код:
ClsA instA = func();
приходится использовать кривое:
Код:
ClsA * pntrA = func();
ClsA instB;
instB = pntrA;
Или не прав?

Последний раз редактировалось Smogg; 03.12.2013 в 18:23.
Smogg вне форума Ответить с цитированием
Старый 03.12.2013, 18:18   #4
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

Тадамммм!! Я все понял. Вот они, досадные плоды самообразования!

Тута должен быть явно описан конструктор копирования, иначе компилятор работает по дефолту:
Код:
	ClsA(ClsA & copy)
	{
		if ( !copy.dat || !copy.sizeDat)
		{
			sizeDat = 0;
			dat = nullptr;	
			return;		
		}
		sizeDat = copy.sizeDat;
		dat = new char[sizeDat];
		std::memcpy(dat, copy.dat, copy.sizeDat);
	}

Последний раз редактировалось Smogg; 03.12.2013 в 21:31.
Smogg вне форума Ответить с цитированием
Старый 04.12.2013, 09:09   #5
nikmoon
Форумчанин
 
Регистрация: 13.11.2013
Сообщений: 149
По умолчанию

Явно объявленный конструктор копирования решил проблему?
nikmoon вне форума Ответить с цитированием
Старый 04.12.2013, 12:45   #6
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

Цитата:
Сообщение от nikmoon Посмотреть сообщение
Явно объявленный конструктор копирования решил проблему?
Ага)
Код:
ClsA ret(){
	ClsA a("sample");
	return a;
}
Потому что в точке return a; функция не мгновенно завершается, а всего лишь конструируется возвращаемый объект и происходит GOTO к самой-самой последней строчке, т.е. "}". Где происходит вызов деструктора локального Cls а и тогда, если возвращаемый объект был создан по дефолту, т.е. просто скопированы члены-данные, то этот объект имеет указатель dat, хоть и равный a.dat, но уже не валидный, ибо для a.dat уже был вызван delete.
Smogg вне форума Ответить с цитированием
Старый 04.12.2013, 13:22   #7
nikmoon
Форумчанин
 
Регистрация: 13.11.2013
Сообщений: 149
По умолчанию

Что по-вашему происходит в таком коде?
Код:
ClsA b = ret();
Я имею ввиду последовательность вызова конструкторов/операторов.
nikmoon вне форума Ответить с цитированием
Старый 04.12.2013, 13:47   #8
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

Цитата:
Сообщение от nikmoon Посмотреть сообщение
Что по-вашему происходит в таком коде?
Код:
ClsA b = ret();
Я имею ввиду последовательность вызова конструкторов/операторов.
Судя по остановкам на бряках, происходят интересные вещи:
1. заходится в функцию ret()
2. в ней конструируется локальный объект a.
3. вызывается return a, каковой на самом деле означает вызов конструктора присваивания b(& a)
4. ипсполняемый код внутри функции закончился и начинается разрушение локальных объектов, т.е. вызов деструктора для а
5. выход из функции ret()
6. исполнение строчки кода, следующей за ClsA b = ret();
Smogg вне форума Ответить с цитированием
Старый 04.12.2013, 13:56   #9
nikmoon
Форумчанин
 
Регистрация: 13.11.2013
Сообщений: 149
По умолчанию

Почему-то мой компилятор такое не проглатывает.
1. Т.к. функция ret() возвращает не ссылку, а именно объект, компилятор требует
определить конструктор ClsA(ClsA), но при его определении ругается, что такой конструктор создать нельзя
2. Если определить функцию ret() так, чтобы она возвращала ссылку, компилятор ругается на возврат локальной переменной.
Т.е. ни в каком случае GCC-4.8.1 не позволяет вернуть локальный объект.

Нет, вру. 2 случай лишь предупреждение, т.е. в принципе работает.

Последний раз редактировалось nikmoon; 04.12.2013 в 14:04.
nikmoon вне форума Ответить с цитированием
Старый 04.12.2013, 14:07   #10
nikmoon
Форумчанин
 
Регистрация: 13.11.2013
Сообщений: 149
По умолчанию

И вообще оказалось достаточно объявить
Код:
const ClsA ret() {...}
Работает даже без ссылки.
nikmoon вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Конструктор класса не хочет принимать в качестве параметра адрес объекта другого класса Jugger Помощь студентам 3 05.01.2012 04:10
[c++] Создание класса. Используя конструктор. Actimel Помощь студентам 2 03.01.2012 11:54
передача функции в конструктор класса Kukurudza Общие вопросы C/C++ 6 04.12.2011 08:31
Конструктор шаблонного класса Hemul Общие вопросы C/C++ 1 01.07.2011 20:21
Конструктор класса XPAiN Общие вопросы Delphi 2 24.01.2010 15:00