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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.83
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 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 при создании объекта
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Raali
572 / 276 / 12
Регистрация: 06.07.2013
Сообщений: 917
Завершенные тесты: 1
25.10.2013, 13:13     Как работает компилятор при создании объекта #2
Цитата Сообщение от Ilot Посмотреть сообщение
Странно. Конструктор копирования в VS не вызывается...
Цитата Сообщение от Ilot Посмотреть сообщение
String s3 = "Немного лет тому назад, там где сливаяся шумят";
это обычный конструктор
C++
1
String(char* s)
novi4ok
549 / 502 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
25.10.2013, 13:17     Как работает компилятор при создании объекта #3
copy constructor применяется, например, так:

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

Добавлено через 53 секунды
Цитата Сообщение от novi4ok Посмотреть сообщение
у тебя перегружен оператор =, я не могу точно сказать, что произойдет с твоим классом в этом случае. поисследуй, разберись, расскажешь.
Не. Перегрузка оператора тут не причем. Это разные вещи.
Raali
572 / 276 / 12
Регистрация: 06.07.2013
Сообщений: 917
Завершенные тесты: 1
25.10.2013, 13:24     Как работает компилятор при создании объекта #5
Цитата Сообщение от Ilot Посмотреть сообщение
Как работает его компилятор?
смотря какой в нем компилятор
castaway
Эксперт С++
4842 / 2981 / 367
Регистрация: 10.11.2010
Сообщений: 11,013
Записей в блоге: 10
Завершенные тесты: 1
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 то он его съест.
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 13:28  [ТС]     Как работает компилятор при создании объекта #7
Цитата Сообщение от Raali Посмотреть сообщение
смотря какой в нем компилятор
Ну так таки в Code::Blocks я пробывал несколько компиляторов: GCC, MV C++ 2005, MV C++ 2010. Все кричат об одно и том же.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
25.10.2013, 13:47     Как работает компилятор при создании объекта #8
Raali, Отнюдь, строка которая вы процитировали
C++
1
String s3 = "Немного лет тому назад, там где сливаяся шумят";
Является ничем иным как
C++
1
String s3(String("Немного лет тому назад, там где сливаяся шумят"));
Конструктор копии вызывается, но на самом деле вызов не обязателен (copy-elision).

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

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

C++
1
2
3
MyClass ob;
MyClass ob2;
ob = ob2;
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
25.10.2013, 13:51     Как работает компилятор при создании объекта #10
novi4ok, Да, извиняюсь, согласен, затормозил. Не заметил, что идет инициализация, а не присваивания уже созданному объекту.
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 13:54  [ТС]     Как работает компилятор при создании объекта #11
Мда castaway сделал как вы сказали заработало как я и говорил в первом посте. Т.е. сперва вызывается конструктор копирования, затем конструктор с одним аргументом. Насколько я понимаю конструктор копирования вызывается так как аргумент это константный указатель и конструктор копирования более подходит к данной ситуации. Однако почему в исходном варианте не вызывается конструктор с одним аргументом - ведь он в точности соответствует аргументам?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
25.10.2013, 13:57     Как работает компилятор при создании объекта #12
Ilot,
Цитата Сообщение от Ilot Посмотреть сообщение
Т.е. сперва вызывается конструктор копирования, затем конструктор с одним аргументом.
Вообщем-то наоборот. Сначала с одним аргументом, а потом конструктор копирования с передачей в него вновь созданного объекта.
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 14:03  [ТС]     Как работает компилятор при создании объекта #13
Цитата Сообщение от ForEveR Посмотреть сообщение
Ilot,
Вообщем-то наоборот. Сначала с одним аргументом, а потом конструктор копирования с передачей в него вновь созданного объекта.
Снова ошибаетесь уважаемый Сперва именно копирования, который вызывает с одним. Проверенно:
Миниатюры
Как работает компилятор при создании объекта  
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 14:06  [ТС]     Как работает компилятор при создании объекта #14
Цитата Сообщение от ForEveR Посмотреть сообщение
Здесь же, из-за того, что конструктор копирования принимает ссылку, нужного конструктора копирования нет, т.к. нельзя привести временный объект к ссылке (в MSVC это компилируется, потому что он допускает как расширение биндинг временног
Я в замешательстве... А разве в конструкторе копирования можно передавать аргумент по значению?
Не приведет ли это к ошибке?
castaway
Эксперт С++
4842 / 2981 / 367
Регистрация: 10.11.2010
Сообщений: 11,013
Записей в блоге: 10
Завершенные тесты: 1
25.10.2013, 14:07     Как работает компилятор при создании объекта #15
Цитата Сообщение от ForEveR Посмотреть сообщение
Вообщем-то наоборот.
Да, мне тоже сначала так показалось.. Но по факту вызывается только один конструктор A( char * s ), что по-сути вроде как и является правильным. Зачем тут конструктор копирования?
Единственный момент, который еще следует поправить, так это изменить конструктор на A( const char * s )
Поправьте если в чем-то ошибся.

Ilot, я предлагаю рассматривать вариант попроще, например мой, и уже от него отталкиваться.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 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
Эксперт С++
4842 / 2981 / 367
Регистрация: 10.11.2010
Сообщений: 11,013
Записей в блоге: 10
Завершенные тесты: 1
25.10.2013, 14:12     Как работает компилятор при создании объекта #17
ForEveR, в твоём примере из 16-го поста у меня выводится только Constructor.
GCC 4.8.2 (-Wall -Wextra -pedantic -O0)

.. пардон, не заметил -fno-elide-constructors
ninja2
 Аватар для 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
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
25.10.2013, 14:18  [ТС]     Как работает компилятор при создании объекта #19
Уважаемый ForEveR может быть я не прав. Однако я считаю, что, пусть даже в вашем коде, сперва будет вызван конструктор копирования, однако встретив аргумент не соответствующий сигнатуре компилятор ищет подходящий конструктор в данном случае с одним аргументом (ук. на char). Поэтому сперва вызывается конструктор копирования, который в свою очередь вызовет конструктор с одним аргументом и затем управление снова вернется к конструктору копирования и будет выполнен его код. Вот именно поэтому сперва идет сообщение от конструктора с одним аргументом, а затем от конструктора копирования.
castaway, полностью с вами солидарен. Мне бы разъяснить, если вам не сложно, почему в этом случае выбирается конструктор копирования. Собственно я и просил вас об этом в 11 посте.
Цитата Сообщение от ForEveR Посмотреть сообщение
Ilot, Я говорю, что должно происходить по стандарту.
Вот это я и спрашивал. Осталось только выяснить почему компилятор Code:Blocks'а ведет себе иначе...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.10.2013, 14:21     Как работает компилятор при создании объекта
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
ninja2
 Аватар для 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("Немного лет тому назад, там где сливаяся шумят")));
Yandex
Объявления
25.10.2013, 14:21     Как работает компилятор при создании объекта
Ответ Создать тему
Опции темы

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