Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.79/14: Рейтинг темы: голосов - 14, средняя оценка - 4.79
Эксперт по математике/физикеЭксперт С++
2048 / 1366 / 395
Регистрация: 16.05.2013
Сообщений: 3,505
Записей в блоге: 6
1

Как работает компилятор при создании объекта

25.10.2013, 13:06. Показов 2939. Ответов 36
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Таки думал разобрался как работает конструктор копирования, а выходит, что нет.
Вопрост состоит в следующем. Имеем код представляющий собой класс для хранения указателей на строки которые хранятся в другом классе(суть в том что бы не хранить в памяти несколько копия строк если они идентичны):
Кликните здесь для просмотра всего текста
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include<iostream>
using namespace std;
////////////////////////////////////////////////////////
class strCount
{
private:
    char* str;
    int count;
    friend class String;
    strCount(char * s)
    {
        str = new char [strlen(s) + 1];
        strcpy(str, s);
        count++;
    }
    ~strCount()
    {
        delete [] str;
    }
};
///////////////////////////////////////////////////
class String
{
private:
    strCount* psc;
public:
    String()
    {
        psc = new strCount("NULL");
    }
 
    String(char* s)
    {
        psc = new strCount(s);
    }
 
    String(String& S)
    {
        psc = S.psc;
        (psc->count)++;
    }
 
    ~String()
    {
        if(psc->count == 1)
            delete psc;
        else
            (psc->count)--;
    }
    String& operator = (String& S)
    {
        if(psc->count == 1)
            delete psc;
        else
            (psc->count)--;
        psc = S.psc;
        (psc->count)++;
        return *this;
    }
    void display()
    {
        cout << psc->str << endl;
    }
};
////////////////////////////////////////////////////
int main()
{
    system("chcp 1251>0");
    String s3 = "Немного лет тому назад, там где сливаяся шумят";
 
    cout << "s3= "; s3.display();
    return 0;
}

Когда я в первый раз читал Лафоре этот код отлично компилился(в то время я работал в VS 6.0).
В данный момент я программирую в среде Code::Blocks и в ней данный код не компилится. Ругается на неоднозначное определение конструктора. Вот отсюда и вопрос:
А что собственно происходит при создании объекта?
Когда запускается конструктор копирования, а когда конструктор с одним аргументом?
Все это время я полагал, что сперва запускается конструктор копирования, а вот он в свою очередь вызывает конструктор с одним аргументом.
Таки все же я не прав или как? Просвятите пожайлуста.

Добавлено через 5 минут
Странно. Конструктор копирования в VS не вызывается...
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.10.2013, 13:06
Ответы с готовыми решениями:

Компилятор выдает ошибку при создании списка
Доброго времени суток всем, не могу понять где ошибка создаю список list самым простым способом...

При объявлении объекта компилятор требует ';'
Есть следующая программа(не законченная): #include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include...

При создании статического объекта получают различные адреса при различных обращениях
Проблема. Описал класс в модуле object.h, там же создал его экземпляр obj. В этом же...

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

36
859 / 448 / 112
Регистрация: 06.07.2013
Сообщений: 1,491
25.10.2013, 13:13 2
Цитата Сообщение от Ilot Посмотреть сообщение
Странно. Конструктор копирования в VS не вызывается...
Цитата Сообщение от Ilot Посмотреть сообщение
String s3 = "Немного лет тому назад, там где сливаяся шумят";
это обычный конструктор
C++
1
String(char* s)
0
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
25.10.2013, 13:17 3
copy constructor применяется, например, так:

C++
1
2
MyClass ob;
MyClass copy = ob;
у тебя перегружен оператор =, я не могу точно сказать, что произойдет с твоим классом в этом случае. поисследуй, разберись, расскажешь.
0
Эксперт по математике/физикеЭксперт С++
2048 / 1366 / 395
Регистрация: 16.05.2013
Сообщений: 3,505
Записей в блоге: 6
25.10.2013, 13:20  [ТС] 4
Цитата Сообщение от novi4ok Посмотреть сообщение
у тебя перегружен оператор =, я не могу точно сказать, что произойдет с твоим классом в этом случае. поисследуй, разберись, расскажешь.
Методом научного тыка выяснилось, что компилятор VS таки адекватно подходит к выбору конструктора:
Тута вызывется конструктор с одним аргументом:
C++
1
    String s3 = "Немного лет тому назад, там где сливаяся шумят";
А здеся конструктор копирования:
C++
1
    String s1(s3);
Так чего от меня хочет Code::Blocks? Как работает его компилятор? Т.е. я хочу спросить как определено поведение компилятора с точки зрения стандарта?

Добавлено через 53 секунды
Цитата Сообщение от novi4ok Посмотреть сообщение
у тебя перегружен оператор =, я не могу точно сказать, что произойдет с твоим классом в этом случае. поисследуй, разберись, расскажешь.
Не. Перегрузка оператора тут не причем. Это разные вещи.
0
859 / 448 / 112
Регистрация: 06.07.2013
Сообщений: 1,491
25.10.2013, 13:24 5
Цитата Сообщение от Ilot Посмотреть сообщение
Как работает его компилятор?
смотря какой в нем компилятор
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
25.10.2013, 13:28 6
Цитата Сообщение от Raali Посмотреть сообщение
смотря какой в нем компилятор
Обычно GCC.

Ilot, ты много всего к кучу смешал. Давай рассмотрим вариант попроще:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <cstring>
 
class A {
    char m_data[256];
 
public:
 
    A( char * s ) {
        strcpy( m_data, s );
    }
 
    A( A & a ) {
        strcpy( m_data, a.m_data );
    }
};
 
int main() {
    A a = "test";
}
Здесь Code::Blocks скорее всего выведет ошибку. Но если в конструкторе перед типом аргумента поставить const то он его съест.
1
Эксперт по математике/физикеЭксперт С++
2048 / 1366 / 395
Регистрация: 16.05.2013
Сообщений: 3,505
Записей в блоге: 6
25.10.2013, 13:28  [ТС] 7
Цитата Сообщение от Raali Посмотреть сообщение
смотря какой в нем компилятор
Ну так таки в Code::Blocks я пробывал несколько компиляторов: GCC, MV C++ 2005, MV C++ 2010. Все кричат об одно и том же.
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
25.10.2013, 13:47 8
Raali, Отнюдь, строка которая вы процитировали
C++
1
String s3 = "Немного лет тому назад, там где сливаяся шумят";
Является ничем иным как
C++
1
String s3(String("Немного лет тому назад, там где сливаяся шумят"));
Конструктор копии вызывается, но на самом деле вызов не обязателен (copy-elision).

Добавлено через 30 секунд
novi4ok, Это не является вызовом конструктор копирования, это именно вызов оператора присваивания.

Добавлено через 3 минуты
Ilot, Код не будет компилироваться ни на одном нормальном компиляторе. Компилятор, даже если не вызывает конструктор копирования ОБЯЗАН проверить, что подходящий конструктор копирования существует. Здесь же, из-за того, что конструктор копирования принимает ссылку, нужного конструктора копирования нет, т.к. нельзя привести временный объект к ссылке (в MSVC это компилируется, потому что он допускает как расширение биндинг временного объекта к ссылке).
2
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
25.10.2013, 13:49 9
Цитата Сообщение от ForEveR Посмотреть сообщение
Это не является вызовом конструктор копирования, это именно вызов оператора присваивания.
ошибаешься, таки копирования. оператор присваивания вызывается здесь:

C++
1
2
3
MyClass ob;
MyClass ob2;
ob = ob2;
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
25.10.2013, 13:51 10
novi4ok, Да, извиняюсь, согласен, затормозил. Не заметил, что идет инициализация, а не присваивания уже созданному объекту.
0
Эксперт по математике/физикеЭксперт С++
2048 / 1366 / 395
Регистрация: 16.05.2013
Сообщений: 3,505
Записей в блоге: 6
25.10.2013, 13:54  [ТС] 11
Мда castaway сделал как вы сказали заработало как я и говорил в первом посте. Т.е. сперва вызывается конструктор копирования, затем конструктор с одним аргументом. Насколько я понимаю конструктор копирования вызывается так как аргумент это константный указатель и конструктор копирования более подходит к данной ситуации. Однако почему в исходном варианте не вызывается конструктор с одним аргументом - ведь он в точности соответствует аргументам?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
25.10.2013, 13:57 12
Ilot,
Цитата Сообщение от Ilot Посмотреть сообщение
Т.е. сперва вызывается конструктор копирования, затем конструктор с одним аргументом.
Вообщем-то наоборот. Сначала с одним аргументом, а потом конструктор копирования с передачей в него вновь созданного объекта.
0
Эксперт по математике/физикеЭксперт С++
2048 / 1366 / 395
Регистрация: 16.05.2013
Сообщений: 3,505
Записей в блоге: 6
25.10.2013, 14:03  [ТС] 13
Цитата Сообщение от ForEveR Посмотреть сообщение
Ilot,
Вообщем-то наоборот. Сначала с одним аргументом, а потом конструктор копирования с передачей в него вновь созданного объекта.
Снова ошибаетесь уважаемый Сперва именно копирования, который вызывает с одним. Проверенно:
Миниатюры
Как работает компилятор при создании объекта  
0
Эксперт по математике/физикеЭксперт С++
2048 / 1366 / 395
Регистрация: 16.05.2013
Сообщений: 3,505
Записей в блоге: 6
25.10.2013, 14:06  [ТС] 14
Цитата Сообщение от ForEveR Посмотреть сообщение
Здесь же, из-за того, что конструктор копирования принимает ссылку, нужного конструктора копирования нет, т.к. нельзя привести временный объект к ссылке (в MSVC это компилируется, потому что он допускает как расширение биндинг временног
Я в замешательстве... А разве в конструкторе копирования можно передавать аргумент по значению?
Не приведет ли это к ошибке?
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
25.10.2013, 14:07 15
Цитата Сообщение от ForEveR Посмотреть сообщение
Вообщем-то наоборот.
Да, мне тоже сначала так показалось.. Но по факту вызывается только один конструктор A( char * s ), что по-сути вроде как и является правильным. Зачем тут конструктор копирования?
Единственный момент, который еще следует поправить, так это изменить конструктор на A( const char * s )
Поправьте если в чем-то ошибся.

Ilot, я предлагаю рассматривать вариант попроще, например мой, и уже от него отталкиваться.
1
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
25.10.2013, 14:08 16
Ilot, Я говорю, что должно происходить по стандарту. Что вызывается в конкретной реализации меня мало интересует. Да и вообще по вашему скрину все так как я и сказал, сначала конструктор с одним параметром, потом конструктор копии.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
 
class Copyable
{
public:
   Copyable(int) { std::cout << "Constructor" << std::endl; }
   Copyable(const Copyable&) { std::cout << "Copy" << std::endl; }
};
 
int main()
{
   Copyable c = 1;
}
Bash
1
2
3
4
g++ -o new new.cpp -fno-elide-constructors
./new
Constructor
Copy
1
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
25.10.2013, 14:12 17
ForEveR, в твоём примере из 16-го поста у меня выводится только Constructor.
GCC 4.8.2 (-Wall -Wextra -pedantic -O0)

.. пардон, не заметил -fno-elide-constructors
0
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
25.10.2013, 14:12 18
Цитата Сообщение от Ilot Посмотреть сообщение
Все это время я полагал, что сперва запускается конструктор копирования, а вот он в свою очередь вызывает конструктор с одним аргументом.
Конструктор копирования вызывается когда копируется объект например:
C++
1
2
A aa(7);//тут конструктор преобразования
A aa1(aa); //тут конструктор копирования
Аргументов у конструктора преобразования может быть сколько угодно.

А неоднозначность от похоже простой пример есть допустим у объекта А конструктор преобразования из double и оператор приведения в double, и если мы запишем например что то врде так:
C++
1
2
A aa;
A bb(a); //тут должно быть неоднозначность две функции могут вызваться как (double) так и A(const A&)
Это может быть пример простецкий да и компиляторы ругаются не все на него возможно, ни в этом примере где вызов конструктора копирования, от не помню вроде если так не будет ругаться то можно записать другой пример:
C++
1
double c=aa+3.14+bb;
тут снова не понятно во что их приводить, то ли double 3.14 приводить к A или наоборот объекты типа A приводить к double.

Все ошибки по неоднозначности легко устраняются применив явный вызов да и все.
0
Эксперт по математике/физикеЭксперт С++
2048 / 1366 / 395
Регистрация: 16.05.2013
Сообщений: 3,505
Записей в блоге: 6
25.10.2013, 14:18  [ТС] 19
Уважаемый ForEveR может быть я не прав. Однако я считаю, что, пусть даже в вашем коде, сперва будет вызван конструктор копирования, однако встретив аргумент не соответствующий сигнатуре компилятор ищет подходящий конструктор в данном случае с одним аргументом (ук. на char). Поэтому сперва вызывается конструктор копирования, который в свою очередь вызовет конструктор с одним аргументом и затем управление снова вернется к конструктору копирования и будет выполнен его код. Вот именно поэтому сперва идет сообщение от конструктора с одним аргументом, а затем от конструктора копирования.
castaway, полностью с вами солидарен. Мне бы разъяснить, если вам не сложно, почему в этом случае выбирается конструктор копирования. Собственно я и просил вас об этом в 11 посте.
Цитата Сообщение от ForEveR Посмотреть сообщение
Ilot, Я говорю, что должно происходить по стандарту.
Вот это я и спрашивал. Осталось только выяснить почему компилятор Code:Blocks'а ведет себе иначе...
0
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
25.10.2013, 14:21 20
Цитата Сообщение от Ilot Посмотреть сообщение
Однако я считаю, что, пусть даже в вашем коде, сперва будет вызван конструктор копирования, однако встретив аргумент не соответствующий сигнатуре компилятор ищет подходящий конструктор в данном случае с одним аргументом (ук. на char).
Нет в твоем коде вызывается вначале конструктор преобразования, затем конструктор копирования, потом оператор присваивания.
Явно все вызови и голову не морочь перепиши эту строчку:
C++
1
String s3 = "Немного лет тому назад, там где сливаяся шумят";
Она эквивалентна:
C++
1
String s3(operetor=(String("Немного лет тому назад, там где сливаяся шумят")));
0
25.10.2013, 14:21
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.10.2013, 14:21
Помогаю со студенческими работами здесь

Ошибка при создании объекта класса
Привет! Чтобы на протяжении всего поста было понятно о чём я говорю,в конце поста прикреплю код....

Ошибка при создании объекта класса
Здравствуйте. В коде ниже при попытке вывести код на экран возникает следующая ошибка: prog.cpp:...

Undefined reference при создании объекта
Есть класс Engine и функция для его инициализации - CreateEngine при попытке создать объект с...

Ошибка при создании объекта класса
Приветствую, форумчане! Возник вопрос при создании объекта класса String. Что самое интересное,...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru