Премини към съдържанието
Форумът в приложение

По-лесно сърфиране. Научи повече.

Kaldata.com - Форуми

Приложение на форума на цял екран с push известия, значки и други.

За да инсталирате това приложение на iOS и iPadOS
  1. Докоснете Иконата за споделяне в Safari
  2. Превъртете менюто и докоснете Добавяне към началния екран.
  3. Докоснете Добавяне в горния десен ъгъл.
За да инсталирате това приложение на Android
  1. Докоснете менюто с 3 точки (⋮) в горния десен ъгъл на браузъра.
  2. Докоснете Добавяне към началния екран или Инсталиране на приложение.
  3. Потвърдете, като докоснете Инсталиране.

Добре дошли!

Добре дошли в нашите форуми, пълни с полезна информация. Имате проблем с компютъра или телефона си? Публикувайте нова тема и ще намерите решение на всичките си проблеми. Общувайте свободно и открийте безброй нови приятели.

Моля, регистрирайте се за да публикувате тема и да получите пълен достъп до всички функции.

 

конструктори за копие при вращане на обект

Featured Replies

здравейте опитвам се да извикам конструктор за копие при връщане на обект от функция при компилиране на този код всичко е добре #include <iostream> #include <cstring> using namespace std; class samp{ char *u; public: samp(); ~samp(){delete u;} samp(const samp &o); char *get(){return u;} void set(char *k); }; samp::samp(){ u=new char[100]; } samp::samp(const samp &o){ u=new char[200]; strcpy(u,o.u); } void samp::set(char *k){ strcpy(u,k); } samp funk(){ samp ob; cout<<"Enter string:"; char a[100]; cin>>a; ob.set(a); return ob; } int main(){ samp ob1; ob1=funk(); cout<<ob1.get()<<"\n"; return 0;} но след изпълнение ми дава грешка явно деструктора на обекта се изжиква след като funk() завърши изпълнението и паметта сочена от ob.u се освобождава как мога да използвам конструктора за копие в този случай

1) В деструктора samp::~samp() { delete u; } трябва да е delete [] u т.е. добави скобите, понеже това е масив!

2) Винаги когато в класовете ти има динамично заделена памет, за този клас трява да имаш задължително copy constructor (имаш такъв), деструктор (имаш такъв) и overload-нат assignment operator. Последният го нямаш и за това ти crash-ва програмата. Присвояваш на ob1 буквалната стойност на указатела u от ob във funk(), която всъщност се delete-ва (от деструктора) при приключването на funk() и ob1.u вече сочи към освободена памет, точно когато се опитваш да я прочетеш с get метода!

Та за да решим проблемът, използваме overload-натия assignment operator:

samp & samp::operator=(samp const & other) {
	if (this != &other) {
		strcpy(this->u, other.u);
	}
	return *this;
}
Компилирай го, пробвай го, че аз пиша на notepad! Кажи ако има проблеми!

Редактирано от synner (преглед на промените)

Използваш погрешно копиращия конструктор.

когато напишеш:

samp ob1;	 // Конструираш обекта.
ob1=funk();   // Присвояване. след изпълнението на оператора се унищожава върнатия обект.

Ей тук са ти грешките. Първо, тъй като обектът вече е конструиран, няма никакъв шанс да му извикаш копиращ конструктор.

Второ, тъй като присвояването не е предефинирано (overloaded), то просто копира обекта (не динамично заделените му данни).

Трето, веднага след това освобождаваме динамично заделените данни с деструктора, след което копието на обекта става с неопределено поведение.

Така ще се извика копиращ конструктор:

samp ob1 = funk();

Редактирано от flare (преглед на промените)

  • Автор

в main() samp ob=funk(); в дефиницията на деструктора delete u[]; така работи мерси благодаря а защо в този случай като не използвам конструктор за копие крашва при изпълнение а когато използвам не крашва и защо тук няма нужда от инициализиране за да се извика конструктора за копие тук предавам обект #include <iostream> #include <cstring> using namespace std; class samp{ char *i; public: samp(); ~samp(){delete []i;} samp(const samp &e); char *get(){return i;} }; samp::samp(){ i=new char[100]; strcpy(i,"This is a test"); } samp::samp(const samp &e){ i=new char[100]; strcpy(i,e.i); } char *funk(samp ob){ return ob.get(); } int main(){ samp ob1; cout<<funk(ob1)<<"\n"; cout<<funk(ob1)<<"\n"; cout<<funk(ob1)<<"\n"; return 0;}

Защото предаваш по стойност. Т.е. всеки път когато извикаш функцията funk, компилатора извиква най-подходящия копиращ конструктор, за да копира параметъра в локална променлива (в твоя случай ob1 в ob). Тъй като твоя обект има динамично заделени данни, си задължен ако предаваш по стойност да имаш валиден копиращ конструктор.

  • Автор

значи когато предавам обект на функция при всяко извикване на функцията се извиква копиращия конструктор т.е този копиращ конструктор който съм дефинирал а когато връщам обект като резултат копиращия конструктор се извиква само един път гогато се инициализира обекта с функцията тоест samp ob1=funk(); нали

значи когато предавам обект на функция при всяко извикване на функцията се извиква копиращия конструктор т.е този копиращ конструктор който съм дефинирал

Не. Копиращ конструктор ще се вика само, когато предаваш по стойност.

Но предаваш ли по стойност, винаги ще се извика някакъв копиращ конструктор. Ако ти си дефинирал подходящ ще е твоя, иначе ще е конструктор по подразбиране, който копира директно обекта. Това обаче не върши работа за динамично заделени данни и затова казах:

Тъй като твоя обект има динамично заделени данни, си задължен ако предаваш по стойност да имаш валиден копиращ конструктор.

а когато връщам обект като резултат копиращия конструктор се извиква само един път гогато се инициализира обекта с функцията тоест samp ob1=funk(); нали

Пак не. Викането на копиращ конструктор няма директна връзка с връщания резултат на функцията. Просто и тук когато създаваш обект, компилаторът се опитва да извика най-подходящия конструктор. В този случай ти казваш, че искаш обекта ти да е копие на върнатия от функцията, затова се извиква копиращ конструктор за да го направи.
  • Автор

да попитам значи когато вращам обект на функция разбрах че не се извиква този копиращ конструктор който съм дефинирал #include <iostream> #include <cstring> using namespace std; class samp{ char *u; public: samp(); ~samp(){delete []u;} samp(const samp &o); char *get(){return u;} void set(char *k); }; samp::samp(){ u=new char[100]; } samp::samp(const samp &o){ cout<<"Copy constructor"; u=new char[200]; strcpy(u,o.u); } void samp::set(char *k){ strcpy(u,k); } samp funk(){ samp ob; cout<<"Enter string:"; char a[100]; cin>>a; ob.set(a); return ob; } int main(){ samp ob1=funk(); cout<<ob1.get()<<"\n"; return 0;} тук не трябва ли да се изпише Copy constructor ако се извиква моя копиращ конструктор ето го изхода Enter string:Arnold Arnold bash-4.1$ и ако не се извиква моя копи конструктор как мога да ползвам моя при връщане на обект

Офф. Изключи си оптимизциите... или използвай нещо, което ще има смисъл от копиращ конструктор. С две думи: Копиращ конструктор би трябвало да се извика. Обаче оптимизатора, като разбере, че създаваш един копие на един обект, който след това унищожаваш, решава да си спести едно излишно копиране и унищожаване.

Редактирано от flare (преглед на промените)

Би трябвало да се вика copy constructor-а за ob1! Какъв компилатор ползваш?

Би трябвало да се вика copy constructor-а за ob1! Какъв компилатор ползваш?

synner по стандарт на оптимизатора му е позволено да не вика изрично копиращ конструктор, ако може да се избегне. И този случай е точно такъв.

Архивирана тема

Темата е твърде стара и е архивирана. Не можете да добавяте нови отговори в нея, но винаги можете да публикувате нова тема, в която да продължи дискусията. Регистрирайте се или влезте във вашия профил за да публикувате нова тема.

Разглеждащи това в момента 0

  • Няма регистрирани потребители разглеждащи тази страница.

Дарение

  • Подкрепи съществуването на форума - направи дарение
    32%
    Дарени 315 € от нужните 1 000 €

Бюлетин

Получавайте известие, когато има важна промяна или новина свързана с форума.

Профил

Навигация

Търсене

Търсене

Конфигуриране на push известия в браузъра

Chrome (Android)
  1. Докоснете иконата на катинар до адресната лента.
  2. Докоснете Разрешения → Известия.
  3. Променете предпочитанията си.
Chrome (Desktop)
  1. Кликнете върху иконата на катинар в адресната лента.
  2. Изберете Настройки на сайта.
  3. Намерете Известия и коригирайте предпочитанията си.