Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.81/16: Рейтинг темы: голосов - 16, средняя оценка - 4.81
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2226 / 1428 / 420
Регистрация: 16.05.2013
Сообщений: 3,651
Записей в блоге: 6

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

25.10.2013, 13:06. Показов 3932. Ответов 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 не вызывается...
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
25.10.2013, 13:06
Ответы с готовыми решениями:

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

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

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

36
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
25.10.2013, 14:24
Лучший ответ Сообщение было отмечено как решение

Решение

Студворк — интернет-сервис помощи студентам
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/quest... itializati

Добавлено через 21 секунду
ninja2, Оператор присваивания тут не зовется.
3
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
25.10.2013, 14:26
Цитата Сообщение от 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 лишь это запрещает.
1
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2226 / 1428 / 420
Регистрация: 16.05.2013
Сообщений: 3,651
Записей в блоге: 6
25.10.2013, 14:26  [ТС]
Цитата Сообщение от ninja2 Посмотреть сообщение
Нет в твоем коде вызывается вначале конструктор преобразования, затем конструктор копирования, потом оператор присваивания.
Явно все вызови и голову не морочь перепиши эту строчку:
C++
1
String s3 = "Немного лет тому назад, там где сливаяся шумят";
Она эквивалентна:
C++
1
String s3(operetor=(String("Немного лет тому назад, там где сливаяся шумят")));
Я под столом.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
25.10.2013, 14:27
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от castaway Посмотреть сообщение
Я правильно понимаю, что в данном примере вызов конструктора копирования не обязателен и это будет соответствовать стандарту?
Абсолютно. Но компилятор ОБЯЗАН проверить, что конструктор с нужной сигнатурой существует.
3
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
25.10.2013, 14:31
Цитата Сообщение от Ilot Посмотреть сообщение
Я под столом.
Аха, да ты можешь как угодно записать явно. Ладно учи тему перегрузка операторов в С++. Без комментариев!!! .
0
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2226 / 1428 / 420
Регистрация: 16.05.2013
Сообщений: 3,651
Записей в блоге: 6
25.10.2013, 14:49  [ТС]
ForEveR, castaway, все парни разобрался. Вы абсолютно правы. Таки у меня там еще одна строчка была в коде:
C++
1
String s1(s3);
Отсюда вылезло сообщение от конструктора копирования. ForEveR, мои извенения.

Добавлено через 9 минут
Таки идем дальше. Мы не выяснили самое главное. Почему в исходном коде компилятор ругается на неоднозначность. Может ли это быть связанно, что он не распознает:
C++
1
    String(String& S)
Как именно конструктор копирования и считает, что это один из обычных конструкторов.
В таком виде все прекрасно компилится:
C++
1
    String(const String& S)
Добавлено через 5 минут
Цитата Сообщение от ForEveR Посмотреть сообщение
Здесь же, из-за того, что конструктор копирования принимает ссылку, нужного конструктора копирования нет, т.к. нельзя привести временный объект к ссылке
ForEveR, вот здесь не совсем понял. А как должен выглядеть конструктор копирования?
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
25.10.2013, 14:51
Ilot, Я уже объяснил в чем проблема. Создается временный объект, который после уходит в конструктор копирования, НО временный объект не может быть привязан к неконстантной ссылке, однако MSVC как расширение позволяет это, чем вообщем-то нарушает стандарт С++. Константную ссылку он принимать должен, чтобы не было таких ситуаций.
2
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
25.10.2013, 14:54
ForEveR, а я почемуто до этой темы всегда считал что если мы так пишем
C++
1
A a = 1;
operator= вызывается, а оно оказывается без него работает.
0
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2226 / 1428 / 420
Регистрация: 16.05.2013
Сообщений: 3,651
Записей в блоге: 6
25.10.2013, 14:57  [ТС]
ForEveR, ага вот теперь все ясно. Благодарю.
0
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
25.10.2013, 14:57
Отак как то A a(operator=(A( int ))); , Ну если есть оператор = то полюбом должна же функция вызваться operator=() ??? Почему тут происходит не понятно как?
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
25.10.2013, 15:00
ninja2, Читаем выше.
C++
1
A a = 1;
это не присваивание, а инициализация копированием.
1
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2226 / 1428 / 420
Регистрация: 16.05.2013
Сообщений: 3,651
Записей в блоге: 6
25.10.2013, 15:01  [ТС]
Цитата Сообщение от ninja2 Посмотреть сообщение
Отак как то A a(operator=(A( int ))); , Ну если есть оператор = то полюбом должна же функция вызваться operator=() ??? Почему тут происходит не понятно как?
Потому что синтаксис языка. Вы же знаток по перегрузкам операторов тогда подумайте почему при перегрузке постфиксного инкрементирования не требуется доп. параметр:
C++
1
operator++(int)
А все потому, что синтаксис и эти выражения идентичны:
C++
1
2
A a(a1);
A b = b1;
0
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
25.10.2013, 15:08
Цитата Сообщение от Ilot Посмотреть сообщение
Вы же знаток по перегрузкам операторов тогда подумайте почему при перегрузке постфиксного инкрементирования не требуется доп. параметр:
Аха, это ты ненавязчиво так спросил? Тот параметр просто как метка что бы знать и перегрузить функцию. Короче синтаксис такой.

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

Добавлено через 2 минуты
Ilot, Ты своим постом всю мою цепочку знаний разломал.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
25.10.2013, 15:11
Ilot,
А все потому, что синтаксис и эти выражения идентичны:
Вроде ж в теме подробно написано, что выражения отнюдь не идентичны. Выражения разные. direct-initialization vs copy-initialization.
1
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
25.10.2013, 15:15
Цитата Сообщение от ForEveR Посмотреть сообщение
A a = 1;
Это походу нужно понимать как вызов конструктора преобразования и потом конструктора копирования. Выделим ключевой момент!!!
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
25.10.2013, 15:28
ninja2, скорее это просто конструктор. Иногда конструктор с конструктором копирования.
1
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
25.10.2013, 15:53
castaway, Ну да.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.10.2013, 15:53

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
37
Ответ Создать тему
Новые блоги и статьи
Эксперимент с картинкой-обложкой на CodinGame
Adler 10.07.2026
Решил на днях провести эксперимент. У меня есть аккаунт на CodinGame, ТОП-3 по РФ среди 2200 участников (в разделе соревнования по программированию ИИ-ботов). Там есть обложка, куда можно влепить. . .
После бана на Пикабу не работает авторизация аккаунта с Яндекса.
Hrethgir 09.07.2026
В частности https:/ / auto. ru/ logbook/ zapret-na-vozhdenie-posle-65-let_1cf28789-07b4-4c75-a2f7-4cd4edf9deeb тут хотел оставить комментарий такой Зрите в корень - монополизация на разработку программ. . .
GitDOS: Когда я решил скрестить MS-DOS, GitHub и Claude
MaGz GoLd 08.07.2026
Привет, Киберфорум! Хочу поделиться своим проектом, который, надеюсь, вас заинтересует. GitDOS — это веб-приложение, которое позволяет запускать DOS в браузере с тремя крутыми фичами: диски живут в. . .
Учебный мини "цифровой двойник" = (Сервер = Java + Flask_питон )+(3D = Гугловскаая 4T nvideo + google colab) +( WMS = Odoo на Docker)
anaschu 07.07.2026
Увидел в требованиях к вакансии создателя имитационных моделей связку (REst + Api + WMS + Anylogic + питон + 3D Nvideo), и решил посмотреть, что это такое. Из этого всего я работал более менее. . .
Море в объективе
kumehtar 06.07.2026
Хотел написать много проникновенных слов, но передумал. Оно само - говорит. Кто слышит тот слышит.
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru