Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
mzarb
-211 / 7 / 1
Регистрация: 14.01.2013
Сообщений: 141
#1

Почему допустимо создавать объект по другому объекту, но нельзя присваивать уже созданный объект, другому созданному объекту? - C++

18.01.2013, 00:05. Просмотров 975. Ответов 22
Метки нет (Все метки)

Это можно :
C++
1
2
3
Array a(10);
a.set(0,5);
Array b(a);
А это нельзя :
C++
1
2
3
Array a(10);
Array b(20);
a = b;
Объясните пожалуйста в чем дело. Если можно, то поподробней, то есть что именно копируется, с каких мест и когда. Я только знаю, что в первом варианте можно так делать, потому что объект ещё не создан, а тонкостей не знаю(.
Вот полный код :
C++
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
26
27
28
29
30
31
32
33
class Array {
private:
    size_t mysize;
    int *mydata;
public:
    Array(size_t size);
    void set(int i, int val);
    int get(int i);
};
 
Array::Array(size_t size){
    mysize = size;
    mydata = new int [mysize];
}
 
void Array::set(int i, int val){
    mydata[i] = val;
}
 
int Array::get(int i){
    return mydata[i];
}
 
int main() {
    Array a(10);
    a.set(0,7);
    Array b(a); //Первый вариант
    
    Array a(10);
    Array b(20);
    b=a;        //Второй вариант
    return 0;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.01.2013, 00:05
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Почему допустимо создавать объект по другому объекту, но нельзя присваивать уже созданный объект, другому созданному объекту? (C++):

Почему конструктор вызывается при присвоении объекта другому объекту - C++
оператор+ выполняется нормально, но когда уже переменная в sum, на след шаге она вызывает конструктор, ибо у меня в примере 9 выходит. А в...

как присвоить значения из одного объекта другому объекту - C++
у меня два объекта, мне надо присвоить значения из одного объекта другому объекту, как это можно сделать #include <iostream> using...

Указатель на целочисленный объект. Указать возможные способы доступа к этому объекту. - C++
здарвствуйте все! помогите пожалуйста с заданиями по мере возможностей: 2) Определив указатель на целочисленный объект, укажите возможные...

Классы. Доступ к созданному объекту. - C++
Доброе утро, форум.:friends: Имеется код, чисто для примера. файл book.h #ifndef BOOK_H #define BOOK_H struct Book {

выделить место для объекта с помощью new или создать указатель, объект и присвоить один другому. какая разница? - C++
кроме того что к объекту созданному с помощью new можно будет обращаться только через указатель.

Правильно созданный глобальный объект - C++
Необходимо создать создать несколько объектов классов глобально. Я делаю: Создаю h-файл. в нем объявляю(создаю) объекты. И в срр -...

22
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
18.01.2013, 00:08 #2
Потому что как только вы объявляете свой конструктор, стандартная копировалка убирается. Чтобы определить свою, определяйте метод Array& Array::operator=(const Array &other), который и выполнит копирование полей из объекта other в текущий (и вернёт этот же текущий, return *this;).
1
TrueBit
95 / 95 / 12
Регистрация: 19.11.2012
Сообщений: 195
18.01.2013, 00:14 #3
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Потому что как только вы объявляете свой конструктор, стандартная копировалка убирается. Чтобы определить свою, определяйте метод Array& Array::operator=(const Array &other), который и выполнит копирование полей из объекта other в текущий (и вернёт этот же текущий, return *this;).
А у меня и без стандартного работает, в а установили в б получили:
C++
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
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
using namespace std;
class Array {
private:
    size_t mysize;
    int * mydata;
public:
    Array(size_t size);
    void set(int i, int val);
    int get(int i);
};
 
Array::Array(size_t size){
    mysize = size;
    mydata = new int [mysize];
}
 
void Array::set(int i, int val){
    mydata[i] = val;
}
 
int Array::get(int i){
    return mydata[i];
}
 
int main() {
    /*Array a(10);
    a.set(0,7);
    Array b(a); //Первый вариант
    */
    
    Array a(10);
    Array b(20);
    a.set(0,777);
    b=a;        //Второй вариант
    cout << b.get(0);
    cin.get();
}
1
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
18.01.2013, 01:10 #4
Ага, но только mydata у них общий. Умрёт один объект и отберёт у второго данные. А по-хорошему объект должен снять копию со всего массива. Ну или обеспечить его неудаление, пока на него кто-то ссылается.
1
Jupiter
Каратель
Эксперт С++
6556 / 3977 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
18.01.2013, 01:13 #5
delete
0
mzarb
-211 / 7 / 1
Регистрация: 14.01.2013
Сообщений: 141
18.01.2013, 01:53  [ТС] #6
Всем спасибо! С конструктором копий и выделением под него нового массива, что бы деструктор первого объекта не удалил его, разобрался. Но вот не понял как он себя вызывает бесконечно, если в его объявлении указать не ссылку на объект, а просто объект, то есть не
C++
1
Array(Array &a)
а это
C++
1
Array(Array a)
.
Можете на пальцах объяснить порядок действий или почему так происходит?
0
Jupiter
Каратель
Эксперт С++
6556 / 3977 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
18.01.2013, 01:59 #7
Цитата Сообщение от mzarb Посмотреть сообщение
а просто объект
если передавать просто объект, то он передается по значению т.е. копируется, вот и получается рекурсия
1
mzarb
-211 / 7 / 1
Регистрация: 14.01.2013
Сообщений: 141
18.01.2013, 18:33  [ТС] #8
Jupiter. То есть он будет восприниматься как ещё один конструктор, а не конструктор копирования и он будет выполнятся после первого конструктора, потому что количество конструкторов неограниченно, если у них разные параметры. А как конструктор получит объект на втором проходе(когда сам себя будет вызывать)? Почитав о рекурсии, все ровно не до конца понимаю как это будет выглядеть на примере с объектом.
Если вам не сложно, то могли бы вы привести какой-то схематический пример как это выглядит в памяти, что копируется, куда и зачем или на словах описать поподробней?
0
Jupiter
Каратель
Эксперт С++
6556 / 3977 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
18.01.2013, 18:51 #9
Цитата Сообщение от mzarb Посмотреть сообщение
То есть он будет восприниматься как ещё один конструктор, а не конструктор копирования
да

Цитата Сообщение от mzarb Посмотреть сообщение
А как конструктор получит объект на втором проходе(когда сам себя будет вызывать)? Почитав о рекурсии, все ровно не до конца понимаю как это будет выглядеть на примере с объектом.
разберитесь в отличии передачи параметров по ссылке, по указателю и по значению
0
MrGluck
Модератор
Эксперт CЭксперт С++
7278 / 4439 / 650
Регистрация: 29.11.2010
Сообщений: 12,017
18.01.2013, 19:02 #10
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Потому что как только вы объявляете свой конструктор, стандартная копировалка убирается.
Убирается лишь конструктор по-умолчанию при явном указании хотя бы одного. Иначе данный код не компилился бы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
class A
{
    public :
        A(){}
};
 
int main()
{
    A a;
    A b = a;
    A c(a);
}
Но определить оператор присваиваний и конструктор копий все же стоит явно т.к.
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
идет работа с памятью и mydata у них общий. Умрёт один объект и отберёт у второго данные.
и память попытается освободиться дважды, что понесет крах во время выполнения.
0
mzarb
-211 / 7 / 1
Регистрация: 14.01.2013
Сообщений: 141
19.01.2013, 00:17  [ТС] #11
Цитата Сообщение от Jupiter Посмотреть сообщение
да


разберитесь в отличии передачи параметров по ссылке, по указателю и по значению
Переменные, в которых сохраняются параметры, передаваемые функции, также являются локальными для этой функции. Эти переменные создаются при вызове функции и в них копируются значения, передаваемые функции в качестве параметров.
С обычными переменными понятно. А вот что копируется из одного объекта в другой так, что при этом вызывается ещё одно копирование, не понятно. Допустим значение должно копироваться в параметр Array(Array a) , то есть это равносильно тому, если в main будет b=a , а потом получается что при копировании объекта "a" в объект "b", объект b дойдет до этого же конструктора Array(Array a) и снова запустить копирование b=a. Даже если это так, то я не понимаю как это выглядит за ширмой, то есть на этапе компиляции, когда уже нету классов. И как по мне, то далеко не уехать, с таким пониманием данного вопроса, по этому и спрашиваю.
0
Kuzia domovenok
1891 / 1746 / 118
Регистрация: 25.03.2012
Сообщений: 5,926
Записей в блоге: 1
19.01.2013, 00:43 #12
Цитата Сообщение от mzarb Посмотреть сообщение
то есть это равносильно тому, если в main будет b=a , а потом получается что при копировании объекта "a" в объект "b", объект b дойдет до этого же конструктора Array(Array a)
Нет, если в main будет b=a, должен вызваться оператор присвоения
0
mzarb
-211 / 7 / 1
Регистрация: 14.01.2013
Сообщений: 141
19.01.2013, 01:04  [ТС] #13
Kuzia domovenok, из-за чего тогда происходит бесконечный вызов?

P.S. Я может быть задаю глупые вопросы, но в моем понимании не хватает какой-то детали, которую возможно вы все здесь считают очевидной и не нужной для объяснения. По этому и прошу максимально подробно описать что происходит в момент копировании и почему это заставляет повторно вызывать копирование.
0
Kuzia domovenok
1891 / 1746 / 118
Регистрация: 25.03.2012
Сообщений: 5,926
Записей в блоге: 1
19.01.2013, 01:14 #14
во-первых, есть разница между присвоением и конструированием копии. Похоже, ты до сих пор не уловил это и говоришь не о том, о чём тебе говорят
C++
1
2
3
4
5
6
7
8
9
10
11
void foo(Array parametr){
//...
}
int main(){
Array a(20);
Array b(a);//вызов конструктора копирования
Array c=a;//вызов конструктора копирования
c=b;//вызов оператора присвоения
foo(a);//вызов конструктора копирования
return 0;
}
Конструктор вызывается при создании новых объектов, Оператор = при изменении существующих.
1
mzarb
-211 / 7 / 1
Регистрация: 14.01.2013
Сообщений: 141
19.01.2013, 02:34  [ТС] #15
Kuzia domovenok, ясно, спасибо за уточнение, но это не дает ответа на мой вопрос. Почему конструктор вызывается бесконечно, если в его параметр передать объект по значению, то есть не по ссылке Array(Array &a), а по значению Array(Array a). Не важно, что это не работает. Меня интересует как это устроено и за счет чего идет бесконечный вызов, а то я встречал только упоминания о нем, а развернутого ответа не нашел, возможно он очевиден, но я его не могу понять. Ещё раз подчеркиваю, мне важно понять как это устроено, а не просто оставить это на поверхностном уровне понимания.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.01.2013, 02:34
Привет! Вот еще темы с ответами:

Как правильно вернуть объект созданный в функции? - C++
Допустим у нас есть функция, которая динамически создает объект и должна его вернуть. К примеру, возьмем динамическое создание массива. ...

Как возвратить указатель на объект, созданный в методе? - C++
A* B::ReturnPtrA(){ A a; a.Method1(a.Method2()); //... return &amp;a; } Говорит, что нельзя возвращать указатель...

Как обратиться к созданному объекту, если переменной присвоен уже другой объект? - Visual Basic
Всем привет, Допустим, у меня есть класс, назовем его MyClass. Я объявляю переменную x, затем присваиваю ей новый созданный объект на...

Как прикрепить линию к объекту и провести к другому объекту ? - Unity, Unity3D
Привет. Вот вариант с помощью метода Gizmos.DrawLine. Как видите линия проходит с центра одного объекта в центр другого. Но задумка...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
19.01.2013, 02:34
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru