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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.83
Ilot
Модератор
Эксперт С++
1807 / 1164 / 226
Регистрация: 16.05.2013
Сообщений: 3,060
Записей в блоге: 5
Завершенные тесты: 1
#1

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

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

Таки думал разобрался как работает конструктор копирования, а выходит, что нет.
Вопрост состоит в следующем. Имеем код представляющий собой класс для хранения указателей на строки которые хранятся в другом классе(суть в том что бы не хранить в памяти несколько копия строк если они идентичны):
Кликните здесь для просмотра всего текста
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 не вызывается...
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.10.2013, 13:06     Как работает компилятор при создании объекта
Посмотрите здесь:

Компилятор выдает ошибку при создании списка - C++
Доброго времени суток всем, не могу понять где ошибка создаю список list самым простым способом #include &lt;list&gt; #include...

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

Undefined reference при создании объекта - C++
Есть класс Engine и функция для его инициализации - CreateEngine при попытке создать объект с помощью Engine *engine =...

Ошибка при создании объекта класса - C++
Здравствуйте. В коде ниже при попытке вывести код на экран возникает следующая ошибка: prog.cpp: In function 'int main()': ...

При создании объекта структуры не вызываются конструкторы - C++
Есть класс Время. У него есть два конструктора. Создал структуру struct List { Time a; List *next; }; При создании объекта...

Ключевое слово class при создании объекта - C++
class A { int r; }; int main () { class A w;//Для чего здесь ключевое слово class? ... }

Ошибки при создании объекта в другом файле - C++
a.h struct Coords { int x; int y; Coords() {}; Coords(int mX, int mY) { x = mX; y = mY; } };

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
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
castaway
Эксперт С++
4881 / 3017 / 370
Регистрация: 10.11.2010
Сообщений: 11,076
Записей в блоге: 10
Завершенные тесты: 1
25.10.2013, 14:12     Как работает компилятор при создании объекта #17
ForEveR, в твоём примере из 16-го поста у меня выводится только Constructor.
GCC 4.8.2 (-Wall -Wextra -pedantic -O0)

.. пардон, не заметил -fno-elide-constructors
ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
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.

Все ошибки по неоднозначности легко устраняются применив явный вызов да и все.
Ilot
Модератор
Эксперт С++
1807 / 1164 / 226
Регистрация: 16.05.2013
Сообщений: 3,060
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 14:18  [ТС]     Как работает компилятор при создании объекта #19
Уважаемый ForEveR может быть я не прав. Однако я считаю, что, пусть даже в вашем коде, сперва будет вызван конструктор копирования, однако встретив аргумент не соответствующий сигнатуре компилятор ищет подходящий конструктор в данном случае с одним аргументом (ук. на char). Поэтому сперва вызывается конструктор копирования, который в свою очередь вызовет конструктор с одним аргументом и затем управление снова вернется к конструктору копирования и будет выполнен его код. Вот именно поэтому сперва идет сообщение от конструктора с одним аргументом, а затем от конструктора копирования.
castaway, полностью с вами солидарен. Мне бы разъяснить, если вам не сложно, почему в этом случае выбирается конструктор копирования. Собственно я и просил вас об этом в 11 посте.
Цитата Сообщение от ForEveR Посмотреть сообщение
Ilot, Я говорю, что должно происходить по стандарту.
Вот это я и спрашивал. Осталось только выяснить почему компилятор Code:Blocks'а ведет себе иначе...
ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
25.10.2013, 14:21     Как работает компилятор при создании объекта #20
Цитата Сообщение от Ilot Посмотреть сообщение
Однако я считаю, что, пусть даже в вашем коде, сперва будет вызван конструктор копирования, однако встретив аргумент не соответствующий сигнатуре компилятор ищет подходящий конструктор в данном случае с одним аргументом (ук. на char).
Нет в твоем коде вызывается вначале конструктор преобразования, затем конструктор копирования, потом оператор присваивания.
Явно все вызови и голову не морочь перепиши эту строчку:
C++
1
String s3 = "Немного лет тому назад, там где сливаяся шумят";
Она эквивалентна:
C++
1
String s3(operetor=(String("Немного лет тому назад, там где сливаяся шумят")));
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
25.10.2013, 14:24     Как работает компилятор при создании объекта #21
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Ilot, Почитайте стандарт.
8.5 Initializers

The initialization that occurs in the form
C++
1
T x = a;
as well as in argument passing, function return, throwing an exception (15.1), handling an exception
(15.3), and aggregate member initialization (8.5.1) is called copy-initialization.
Про copy-initialization почитайте сами, вырезки из стандарта мне кидать лень. Но суть в том, что сначала выбирается конструктор преобразования, который может принять объект находящийся с правой стороны оператора присваивания (const char* в данном случае), после чего, если такой конструктор найден - конструируется объект, используя конструктор с этим параметром, после конструирования объекта компилятор проверяет, что конструктор копирования с нужной сигнатурой имеет место быть, если нет - кидает ошибку, если есть может вызвать, а может не вызвать конструктор копирования, зависит от настроек компилятора.

Если позволяет английский более подробно можно прочесть тут: http://stackoverflow.com/questions/1...t-initializati

Добавлено через 21 секунду
ninja2, Оператор присваивания тут не зовется.
castaway
Эксперт С++
4881 / 3017 / 370
Регистрация: 10.11.2010
Сообщений: 11,076
Записей в блоге: 10
Завершенные тесты: 1
25.10.2013, 14:26     Как работает компилятор при создании объекта #22
Цитата Сообщение от Ilot Посмотреть сообщение
castaway, полностью с вами солидарен. Мне бы разъяснить, если вам не сложно, почему в этом случае выбирается конструктор копирования. Собственно я и просил вас об этом в 11 посте.
Цитата Сообщение от Ilot Посмотреть сообщение
Однако почему в исходном варианте не вызывается конструктор с одним аргументом - ведь он в точности соответствует аргументам?
О каком одном аргументе идет речь? В следующем примере у меня выводит A( int )
C++
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
 
struct A {
    int i;
    A( int ) { std::cout << "A( int )\n"; }
    A( const A & ) { std::cout << "A( const A & )\n"; }
};
 
int main() {
    A a = 1;
}
и это в принципе логично.

ForEveR, это конечно все верно, но
The C++ standard allows an implementation to omit creating a temporary which is only used to initialize another object of the same type.
Я правильно понимаю, что в данном примере вызов конструктора копирования не обязателен и это будет соответствовать стандарту?
А флаг -fno-elide-constructors лишь это запрещает.
Ilot
Модератор
Эксперт С++
1807 / 1164 / 226
Регистрация: 16.05.2013
Сообщений: 3,060
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 14:26  [ТС]     Как работает компилятор при создании объекта #23
Цитата Сообщение от ninja2 Посмотреть сообщение
Нет в твоем коде вызывается вначале конструктор преобразования, затем конструктор копирования, потом оператор присваивания.
Явно все вызови и голову не морочь перепиши эту строчку:
C++
1
String s3 = "Немного лет тому назад, там где сливаяся шумят";
Она эквивалентна:
C++
1
String s3(operetor=(String("Немного лет тому назад, там где сливаяся шумят")));
Я под столом.
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
25.10.2013, 14:27     Как работает компилятор при создании объекта #24
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от castaway Посмотреть сообщение
Я правильно понимаю, что в данном примере вызов конструктора копирования не обязателен и это будет соответствовать стандарту?
Абсолютно. Но компилятор ОБЯЗАН проверить, что конструктор с нужной сигнатурой существует.
ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
25.10.2013, 14:31     Как работает компилятор при создании объекта #25
Цитата Сообщение от Ilot Посмотреть сообщение
Я под столом.
Аха, да ты можешь как угодно записать явно. Ладно учи тему перегрузка операторов в С++. Без комментариев!!! .
Ilot
Модератор
Эксперт С++
1807 / 1164 / 226
Регистрация: 16.05.2013
Сообщений: 3,060
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 14:49  [ТС]     Как работает компилятор при создании объекта #26
ForEveR, castaway, все парни разобрался. Вы абсолютно правы. Таки у меня там еще одна строчка была в коде:
C++
1
String s1(s3);
Отсюда вылезло сообщение от конструктора копирования. ForEveR, мои извенения.

Добавлено через 9 минут
Таки идем дальше. Мы не выяснили самое главное. Почему в исходном коде компилятор ругается на неоднозначность. Может ли это быть связанно, что он не распознает:
C++
1
    String(String& S)
Как именно конструктор копирования и считает, что это один из обычных конструкторов.
В таком виде все прекрасно компилится:
C++
1
    String(const String& S)
Добавлено через 5 минут
Цитата Сообщение от ForEveR Посмотреть сообщение
Здесь же, из-за того, что конструктор копирования принимает ссылку, нужного конструктора копирования нет, т.к. нельзя привести временный объект к ссылке
ForEveR, вот здесь не совсем понял. А как должен выглядеть конструктор копирования?
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
25.10.2013, 14:51     Как работает компилятор при создании объекта #27
Ilot, Я уже объяснил в чем проблема. Создается временный объект, который после уходит в конструктор копирования, НО временный объект не может быть привязан к неконстантной ссылке, однако MSVC как расширение позволяет это, чем вообщем-то нарушает стандарт С++. Константную ссылку он принимать должен, чтобы не было таких ситуаций.
ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
25.10.2013, 14:54     Как работает компилятор при создании объекта #28
ForEveR, а я почемуто до этой темы всегда считал что если мы так пишем
C++
1
A a = 1;
operator= вызывается, а оно оказывается без него работает.
Ilot
Модератор
Эксперт С++
1807 / 1164 / 226
Регистрация: 16.05.2013
Сообщений: 3,060
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 14:57  [ТС]     Как работает компилятор при создании объекта #29
ForEveR, ага вот теперь все ясно. Благодарю.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.10.2013, 14:57     Как работает компилятор при создании объекта
Еще ссылки по теме:

Ошибка LNK2019 При динамическом создании объекта - C++
Это хидер который я создал #include&lt;math.h&gt; #define PI 3.14 class Figure { public: Figure(); virtual ~Figure();

ООП в C++: Вызов родительского конструктора с параметром при создании объекта дочернего класса - C++
Здравствуйте! Столкнулся с такой проблемой: если есть родительский класс с конструктором, то при создании дочернего объекта от этого...

Как работает компилятор С++ - C++
Подскажите, как происходит компиляция исходного кода, написанного на С++? К примеру мы имеем файл test.cpp, в котором написан код...

Не работает класс при передаче в функцию объекта - C++
Всем привет, я не пойму подскажите куда правильно подставить #include &quot;doodler.h&quot; чтобы не было ошибок. Есть класс, который содержит...

Как компилятор узнаёт о размере массива при выполнении операции delete? - C++
Такой глупый вопрос появился при изучении операций new и delete. Я создаю указатель на массив int с помощью операции new. int size; ...


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

Или воспользуйтесь поиском по форуму:
ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
25.10.2013, 14:57     Как работает компилятор при создании объекта #30
Отак как то A a(operator=(A( int ))); , Ну если есть оператор = то полюбом должна же функция вызваться operator=() ??? Почему тут происходит не понятно как?
Yandex
Объявления
25.10.2013, 14:57     Как работает компилятор при создании объекта
Ответ Создать тему
Опции темы

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