Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.60/15: Рейтинг темы: голосов - 15, средняя оценка - 4.60
0 / 0 / 0
Регистрация: 04.04.2016
Сообщений: 20

Компилятор игнорирует явный конструктор копирования

08.04.2016, 10:25. Показов 3936. Ответов 36
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Уже в который раз возникают проблемы с конструкторами класса и вот очередная из них. Насколько я понял, компилятор игнорирует явно написанный конструктор копирования и использует тот, что по умолчанию, в итоге в двух разных объектах поля last_name имеют один и тот же адрес, что вызывает ошибку при выполнении деструктора, который высвобождает динамическую память. Как заставить компилятор использовать мой конструктор копирования и если проблема не в этом, тогда что делать?
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
#include <iostream>
using namespace std;
class account
{
public:
    int MAX = 50;
    account()
    {
        last_name = new char[MAX];
        strcpy_s(last_name, MAX,"Skuratovich");
    }
    
    account(const char *_last_name)
    {
        
        last_name = new char[MAX];
        strcpy_s(last_name, strlen(_last_name)+1, _last_name);
        cout << "я сработалъ!" << endl;
    }
    account(account& copy)
    {
        last_name = new char[MAX];
        strcpy_s(last_name, strlen(copy.last_name) + 1, copy.last_name);
        cout << "я сработалъ!" << endl;
    }
 
    ~account() { delete[] last_name; }
 
private:
    char *last_name;
 
};
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
08.04.2016, 10:25
Ответы с готовыми решениями:

Явный конструктор копирования в c++
Когда в программе нужен явный конструктор копирования?

Объясните, зачем в коде нужен явный конструктор копирования
Добрый день, хочу понять код, почему тут обезательно надо явный конструктор копирования? #include &lt;iostream&gt; using...

Явный и неявный конструктор
явный конструктор-это...? неявный конструктор-это...? спасибо.

36
 Аватар для Kastaneda
5232 / 3206 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
08.04.2016, 11:09
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от mimicria Посмотреть сообщение
Прошу прощения за древний текст, но:
12.8 Copying class objects
2. A nontemplate constructor for class X is a copy constructor if its first parameter is of type X&, const X&,
volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments
Честно говоря стандарта под рукой не было, поэтому так написал. Возможно это нововведение С++11, но я точно знаю, что раньше конструктор копирования без const не воспринимался многими компиляторами (в студии работал). И это довольно известная проблема, на форуме не раз обсуждалось.

Добавлено через 3 минуты

Не по теме:

Croessmah, есть 2003 стандарт? На iso сайте только последний нашел. Интересно, что там пишут по этому поводу.

0
Падаван С++
 Аватар для obivan
447 / 261 / 89
Регистрация: 11.11.2014
Сообщений: 916
08.04.2016, 11:13
Pink_Pank, ну говорю же лично для меня, такой new новое, буду знать
Цитата Сообщение от Pink_Pank Посмотреть сообщение
нужен либо Placement new, либо отдельный инициализирующий метод
initializer_list

Добавлено через 3 минуты
Pink_Pank, про Placement new обязательно почитаю

Не по теме:

Тема оказалась полезнее для меня чем для ТС`а :)

0
47 / 31 / 21
Регистрация: 04.04.2016
Сообщений: 209
08.04.2016, 11:15
Деструктору имеет смысл справляться только с освобождением выделенной памяти. А остальное - проблемы компилятора. И то, с использованием умных указателей, и проблема возврата памяти плавно перелазит на плечи компиля.
0
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
08.04.2016, 12:00
Цитата Сообщение от Kastaneda Посмотреть сообщение
Croessmah, есть 2003 стандарт?
У меня есть.
12.8 Copying class objects [class.copy]
1 A class object can be copied in two ways, by initialization (12.1, 8.5), including for function argument passing (5.2.2)
and for function value return (6.6.3), and by assignment (5.17). Conceptually, these two operations are implemented by
a copy constructor (12.1) and copy assignment operator (13.5.3).
2 A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X&
or const volatile X&, and either there are no other parameters or else all other parameters have default arguments
(8.3.6).112) [ Example: X::X(const X&) and X::X(X&,int=1) are copy constructors.
C++
1
2
3
4
5
6
 class X {
           / / ...
       public :
           X ( int );
           X ( const X & , int = 1);
       };
112) Because a template constructor is never a copy constructor, the presence of such a template does not suppress the implicit declaration of a copy

constructor. Template constructors participate in overload resolution with other constructors, including copy constructors, and a template constructor
may be used to copy an object if it provides a better match than other constructors.
Добавлено через 1 минуту
Могу весь раздел вбабахать, если надо.
2
08.04.2016, 12:05

Не по теме:

Цитата Сообщение от HighPredator Посмотреть сообщение
Могу весь раздел вбабахать, если надо.
спасибо, не надо. Блин, откуда у меня в памяти сидит, что без const не работает, никак не могу вспомнить.

0
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
08.04.2016, 12:11
Цитата Сообщение от Kastaneda Посмотреть сообщение
Блин, откуда у меня в памяти сидит, что без const не работает, никак не могу вспомнить.
Я думаю, что это не столько "не работает" в общем, сколько "не работает, если аргумент является временным объектом" в частности. Видимо у вас это в подкорке так отложилось.
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
08.04.2016, 12:42
не успел цитату с стандарта 12.8.2 выложили уже)
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
08.04.2016, 13:11
Цитата Сообщение от Siarhey Посмотреть сообщение
Как заставить компилятор использовать мой конструктор копирования и если проблема не в этом, тогда что делать?
Реализуй для начала оператор присваивания, а там посмотрим.
Сдается мне, что конструктор копирования здесь вообще не при чем.
1
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
08.04.2016, 13:28
Цитата Сообщение от Siarhey Посмотреть сообщение
Уже в который раз возникают проблемы с конструкторами класса
К предыдущему посту Убежденный хочу добавить, что неоднократные проблемы ТС в этой теме связаны с тем, что он не понимает, в частности, чем отличается копирование от присваивания и не отличает их в своем коде друг от друга. Проблемы так и будут продолжаться, пока автор не разберется в этом.

Добавлено через 11 минут
Цитата Сообщение от obivan Посмотреть сообщение
что тогда будет с другими полями, допустим не указателями, подкинем мы поле int, и что оно 2 раза будет создаватся, а декструктор тогда как с этим справтся
Никак. Это UB. Нельзя поверх живого объекта создавать еще один.
Но можно распределить память (например через operator new или malloc), а затем создать в ней объект с помощью placement new. Реализация стандартных контейнеров (в частности vector) пользуется именно этим.

По поводу инициализации элементов массивов см. пример.
По поводу подводных камней при использовании placement new для присваивания объектов см. эту тему.
2
0 / 0 / 0
Регистрация: 04.04.2016
Сообщений: 20
08.04.2016, 17:47  [ТС]
obivan, Я так и не понял что мне конкретно исправить)

Добавлено через 4 минуты
Цитата Сообщение от Pink_Pank Посмотреть сообщение
Попробуйте писать this->last_name
где именно?)

Добавлено через 11 минут
DrOffset, то есть, чтобы пользоваться конструктором копирования, мне нужно иметь "пустой" объект? или я неправильно понимаю? Как мне именно написать?
0
 Аватар для Kastaneda
5232 / 3206 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
08.04.2016, 17:59
Siarhey, пока место в коде, где по-твоему конструктор копирования не работает, мы уже 2 страницы гадаем в чем проблема, можем и дальше продолжать)
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
08.04.2016, 18:07
Лучший ответ Сообщение было отмечено Siarhey как решение

Решение

Цитата Сообщение от Siarhey Посмотреть сообщение
компилятор игнорирует явно написанный конструктор копирования
В языке С++ есть масса контекстов, в которых компилятор действительно имеет право игнорировать создание копии (и вызов конструктора копирования), даже если конструктор копирования имеет какие-то побочные эффекты.

Цитата Сообщение от Pink_Pank Посмотреть сообщение
Во первых, у вас утечка памяти в вашем копирующем конструкторе. Что если у вас объект уже создан ( выделили память),
В конструкторе (в любой конструкторе) никогда не бывает "объект уже создан". Память объекта в момент начала работы конструктора всегда содержит мусор. Задача конструктора - сделать эту память не мусором, т.е. проинициализировать ее. Именно для этого и существуют конструкторы: превратить сырую непредсказуемую память в корректное начальное состояние объекта.

Конструктор - это всегда "самый первый" метод объекта, работающий на регионе памяти. До него никого не было. Если у вас в конструкторе есть какая-то завязка на исходное содержимое инициализируемой памяти - значит вы что-то делаете неправильно.

Цитата Сообщение от Pink_Pank Посмотреть сообщение
Placement new посмотрите
Если вы вызовете placement new не уже сконструированный объект, требующий нетривиального уничтожения - это ваша грубая ошибка и ваша программа имеет неопределенное поведение.

Еще раз: конструктор всегда считает, что вызывается на сырую память. Без вариантов. Никакого удаления предыдущих данных в конструкторе нет и быть не может. В момент начала работы конструктора память содержит мусор и анализировать этот мусор никакого смысла нет.

Цитата Сообщение от Pink_Pank Посмотреть сообщение
Это не хак.
Это хак, и очень грубый хак.

Цитата Сообщение от Pink_Pank Посмотреть сообщение
попробуйте-ка выделить через new память для массива из классов и сразу же их в этой форме проинициализировать. Не получится. у вас классы создадутся при помощи конструктора по умолчанию.
Совершенно верно.

Цитата Сообщение от Pink_Pank Посмотреть сообщение
А чтобы их проинициализировать нужен либо Placement new,
Нет. Если объекты уже сконструированы (при помощи конструктора по умолчанию), то конструировать их поверх еще раз через placement new уже запрещается.

Чтобы в такой ситуации легально применить placement new, надо будет сначала вручную деструктировать эти объекты вызовом деструктора.

Цитата Сообщение от Pink_Pank Посмотреть сообщение
либо отдельный инициализирующий метод
Только так - отдельный инициализирующий метод.

Либо исходный массив надо было выделять как буфер из char, и тогда можно было бы поверх пройтись placement new. Но ни в коем случае не идти по уже сконструированным объектам через placement new.

В любом случае, еще раз: любая попытка анализировать предыдущее состояние объекта в конструкторе - всегда ошибка. "Предыдущего состояния" у конструируемого объекта нет. Объект всегда конструируется в сырой неинициализированной памяти.

Цитата Сообщение от Kastaneda Посмотреть сообщение
нет, const говорит, что это конструктор копирования в соответствии со стандартом, без const это не пойми что.
Это, конечно, не верно.

Конструктором копирования класса C называется конструктор, у которого первый параметр имеет тип C &, const C &, volatile C & или const volatile C & и либо больше нет параметров вообще, либо все остальные параметры имеют аргументы по умолчанию.[/quote]
1
0 / 0 / 0
Регистрация: 04.04.2016
Сообщений: 20
08.04.2016, 18:08  [ТС]
Kastaneda,крч вот мэйн (операции присваивания и вывода на экран я перегрузил, просто стёр в заголовочном для читабельности, но я уверен, там всё правильно)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "stdafx.h"
 
int main()
{
    setlocale(LC_ALL, "Russian");
    account NEW("Skuratovich"), NEW2; 
    cout << NEW;
    NEW = "Ivanov"; // меняем владельца
    cout << NEW;
    cout << "NEW2 с использование конструктора без параметров" << endl;
    cout << NEW2; //для демонстрации использования конструктора без параметров
    NEW2 = NEW; // использование конструктора копирования
    cout << "NEW2 после использования конструктора копирования" << endl;
    cout << NEW2;
    system("pause");
    return 0;
}
0
 Аватар для Kastaneda
5232 / 3206 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
08.04.2016, 18:10
Лучший ответ Сообщение было отмечено Siarhey как решение

Решение

Не по теме:

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Это, конечно, не верно.
TheCalligrapher, да, это уже выяснили, был не прав.



Добавлено через 1 минуту
Вот же оно
Цитата Сообщение от Siarhey Посмотреть сообщение
NEW2 = NEW; // использование конструктора копирования
тебе выше написали
Цитата Сообщение от DrOffset Посмотреть сообщение
неоднократные проблемы ТС в этой теме связаны с тем, что он не понимает, в частности, чем отличается копирование от присваивания и не отличает их в своем коде друг от друга. Проблемы так и будут продолжаться, пока автор не разберется в этом.
советую все таки разобраться.
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
08.04.2016, 18:13
Цитата Сообщение от Siarhey Посмотреть сообщение
крч вот мэйн
Ни одной попытки использования конструктора копирования в этом коде нет даже отдаленно.
1
0 / 0 / 0
Регистрация: 04.04.2016
Сообщений: 20
08.04.2016, 18:17  [ТС]
Kastaneda, всё, вроде бы понял, спасибо)

Добавлено через 2 минуты
TheCalligrapher, а вот так будет?
C++
1
account NEW("Skuratovich"), NEW2(NEW)
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
08.04.2016, 18:18
Цитата Сообщение от Siarhey Посмотреть сообщение
а вот так будет?
Так будет. Боле того, теоретически и вот так будет

C++
1
account NEW = "Skuratovich";
но практически компилятор скорее всего соптимизирует код и удалит вызов конструктора копирования в этом случае.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
08.04.2016, 18:18

Как использовать явный конструктор родительского класса?
Привет :) Вот код, строчка 43. Как использовать конструктор типа A(int), в классе C? Компилятор выдаёт ошибку (Error:...

Не могу сделать чтобы класс содержал основной конструктор и конструктор копирования
Разработать класс ThreeAngle для работы с плоскими треугольниками. В качестве членов-данных задаются длины трех сторон треугольника. Класс...

Конструктор класса, конструктор копирования запускается не тот который нужен
Есть такой конструктор: Neuron::Neuron(int iType_activation_funk) { this-&gt;iType_act = iType_activation_funk; switch...

Не могу правильно сделать конструктор и конструктор копирования и принадлежность точки с заданными координатами треугольнику
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;conio.h&gt; #include &lt;windows.h&gt; #include &lt;math.h&gt; #include &lt;algorithm&gt; using...

Компилятор игнорирует функции cin, if, for
После запуска программа дает ввести только строку. После чего выбивается весь cout, игнорируя и функции cin, и разветвление іf и циклы for....


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

Или воспользуйтесь поиском по форуму:
37
Ответ Создать тему
Новые блоги и статьи
Оказывается, Unreal Engine позволяет качество на порядки выше, чем было в Lineedge
Etyuhibosecyu 05.07.2026
Жаль, конечно, что я не узнал об этом, пока Lineedge существовала, а то бы Noname2331 написал, что волки превращаются в пиксельную кашу, а я бы его попросил скачать какую-нибудь бриллиантовую или Pro. . .
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 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru