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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.83
Ilot
Модератор
Эксперт С++
1767 / 1142 / 223
Регистрация: 16.05.2013
Сообщений: 3,020
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 13:06     Как работает компилятор при создании объекта #1
Таки думал разобрался как работает конструктор копирования, а выходит, что нет.
Вопрост состоит в следующем. Имеем код представляющий собой класс для хранения указателей на строки которые хранятся в другом классе(суть в том что бы не хранить в памяти несколько копия строк если они идентичны):
Кликните здесь для просмотра всего текста
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++
ООП в C++: Вызов родительского конструктора с параметром при создании объекта дочернего класса C++
Использование объекта одного класса при создании нового класса C++
При создании объекта структуры не вызываются конструкторы C++
C++ Undefined reference при создании объекта
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 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
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 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
Модератор
Эксперт С++
1767 / 1142 / 223
Регистрация: 16.05.2013
Сообщений: 3,020
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 14:26  [ТС]     Как работает компилятор при создании объекта #23
Цитата Сообщение от ninja2 Посмотреть сообщение
Нет в твоем коде вызывается вначале конструктор преобразования, затем конструктор копирования, потом оператор присваивания.
Явно все вызови и голову не морочь перепиши эту строчку:
C++
1
String s3 = "Немного лет тому назад, там где сливаяся шумят";
Она эквивалентна:
C++
1
String s3(operetor=(String("Немного лет тому назад, там где сливаяся шумят")));
Я под столом.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
25.10.2013, 14:27     Как работает компилятор при создании объекта #24
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от castaway Посмотреть сообщение
Я правильно понимаю, что в данном примере вызов конструктора копирования не обязателен и это будет соответствовать стандарту?
Абсолютно. Но компилятор ОБЯЗАН проверить, что конструктор с нужной сигнатурой существует.
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
25.10.2013, 14:31     Как работает компилятор при создании объекта #25
Цитата Сообщение от Ilot Посмотреть сообщение
Я под столом.
Аха, да ты можешь как угодно записать явно. Ладно учи тему перегрузка операторов в С++. Без комментариев!!! .
Ilot
Модератор
Эксперт С++
1767 / 1142 / 223
Регистрация: 16.05.2013
Сообщений: 3,020
Записей в блоге: 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
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
25.10.2013, 14:51     Как работает компилятор при создании объекта #27
Ilot, Я уже объяснил в чем проблема. Создается временный объект, который после уходит в конструктор копирования, НО временный объект не может быть привязан к неконстантной ссылке, однако MSVC как расширение позволяет это, чем вообщем-то нарушает стандарт С++. Константную ссылку он принимать должен, чтобы не было таких ситуаций.
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
25.10.2013, 14:54     Как работает компилятор при создании объекта #28
ForEveR, а я почемуто до этой темы всегда считал что если мы так пишем
C++
1
A a = 1;
operator= вызывается, а оно оказывается без него работает.
Ilot
Модератор
Эксперт С++
1767 / 1142 / 223
Регистрация: 16.05.2013
Сообщений: 3,020
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 14:57  [ТС]     Как работает компилятор при создании объекта #29
ForEveR, ага вот теперь все ясно. Благодарю.
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
25.10.2013, 14:57     Как работает компилятор при создании объекта #30
Отак как то A a(operator=(A( int ))); , Ну если есть оператор = то полюбом должна же функция вызваться operator=() ??? Почему тут происходит не понятно как?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
25.10.2013, 15:00     Как работает компилятор при создании объекта #31
ninja2, Читаем выше.
C++
1
A a = 1;
это не присваивание, а инициализация копированием.
Ilot
Модератор
Эксперт С++
1767 / 1142 / 223
Регистрация: 16.05.2013
Сообщений: 3,020
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 15:01  [ТС]     Как работает компилятор при создании объекта #32
Цитата Сообщение от ninja2 Посмотреть сообщение
Отак как то A a(operator=(A( int ))); , Ну если есть оператор = то полюбом должна же функция вызваться operator=() ??? Почему тут происходит не понятно как?
Потому что синтаксис языка. Вы же знаток по перегрузкам операторов тогда подумайте почему при перегрузке постфиксного инкрементирования не требуется доп. параметр:
C++
1
operator++(int)
А все потому, что синтаксис и эти выражения идентичны:
C++
1
2
A a(a1);
A b = b1;
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
25.10.2013, 15:08     Как работает компилятор при создании объекта #33
Цитата Сообщение от Ilot Посмотреть сообщение
Вы же знаток по перегрузкам операторов тогда подумайте почему при перегрузке постфиксного инкрементирования не требуется доп. параметр:
Аха, это ты ненавязчиво так спросил? Тот параметр просто как метка что бы знать и перегрузить функцию. Короче синтаксис такой.

Добавлено через 1 минуту
Цитата Сообщение от Ilot Посмотреть сообщение
А все потому, что синтаксис и эти выражения идентичны:
Ну ок будем знать. Ну я еще проверю. Все мои стереотипы поломались.

Добавлено через 2 минуты
Ilot, Ты своим постом всю мою цепочку знаний разломал.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
25.10.2013, 15:11     Как работает компилятор при создании объекта #34
Ilot,
А все потому, что синтаксис и эти выражения идентичны:
Вроде ж в теме подробно написано, что выражения отнюдь не идентичны. Выражения разные. direct-initialization vs copy-initialization.
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
25.10.2013, 15:15     Как работает компилятор при создании объекта #35
Цитата Сообщение от ForEveR Посмотреть сообщение
A a = 1;
Это походу нужно понимать как вызов конструктора преобразования и потом конструктора копирования. Выделим ключевой момент!!!
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
25.10.2013, 15:28     Как работает компилятор при создании объекта #36
ninja2, скорее это просто конструктор. Иногда конструктор с конструктором копирования.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.10.2013, 15:53     Как работает компилятор при создании объекта
Еще ссылки по теме:

C++ Как работает компилятор С++
Ошибка LNK2019 При динамическом создании объекта C++
C++ Ключевое слово class при создании объекта

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

Или воспользуйтесь поиском по форуму:
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
25.10.2013, 15:53     Как работает компилятор при создании объекта #37
castaway, Ну да.
Yandex
Объявления
25.10.2013, 15:53     Как работает компилятор при создании объекта
Ответ Создать тему
Опции темы

Текущее время: 16:23. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru