0 / 0 / 4
Регистрация: 09.04.2016
Сообщений: 128
1

Конструктор копирования в С++

25.06.2018, 22:00. Показов 2132. Ответов 22
Метки нет (Все метки)

Такой вопрос, работает ли такой синтаксис, если я передаю указатель на объект, а не объект?

C++
1
2
3
4
имяКласса (const имяКласса & object)
{
    //код конструктора копирования
}
не лучше ли сделать так?:
C++
1
2
3
4
имяКласса (имяКласса * object)
{
    //код конструктора копирования
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.06.2018, 22:00
Ответы с готовыми решениями:

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

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

Не могу правильно сделать конструктор и конструктор копирования и принадлежность точки с заданными координатами треугольнику
#include "stdafx.h" #include <iostream> #include <conio.h> #include <windows.h> #include...

Конструктор инициализации, конструктор копирования, деструктор
Я сделал почти задание по перегрузке операторов. Осталось одно, тоесть три: конструктор...

22
192 / 128 / 52
Регистрация: 19.01.2010
Сообщений: 518
25.06.2018, 22:33 2
Цитата Сообщение от IlushaMax Посмотреть сообщение
имяКласса (const имяКласса & object)
он так и пишется. И это не указатель на объект, а константная ссылка
Цитата Сообщение от IlushaMax Посмотреть сообщение
не лучше ли сделать так?:
а чем это лучше? а вдруг nullptr подпихнут?
0
1369 / 513 / 71
Регистрация: 21.07.2015
Сообщений: 1,298
26.06.2018, 00:09 3
Цитата Сообщение от IlushaMax Посмотреть сообщение
не лучше ли сделать так?
А чем должно быть лучше?

Добавлено через 36 секунд
Цитата Сообщение от Selot Посмотреть сообщение
а вдруг nullptr подпихнут?
Nullptr могут и через ссылку подпихнуть.
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
26.06.2018, 00:17 4
Цитата Сообщение от shmkv Посмотреть сообщение
Nullptr могут и через ссылку подпихнуть
Нет, не могут.
0
1369 / 513 / 71
Регистрация: 21.07.2015
Сообщений: 1,298
26.06.2018, 01:12 5
Цитата Сообщение от New man Посмотреть сообщение
Нет, не могут.
C++
1
2
T *p = nullptr;
f(*p);
0
Комп_Оратор)
Эксперт по математике/физике
8789 / 4544 / 612
Регистрация: 04.12.2011
Сообщений: 13,549
Записей в блоге: 16
26.06.2018, 01:35 6
Цитата Сообщение от New man Посмотреть сообщение
Нет, не могут.
C++
1
2
3
4
A* pa = new A();
A& ra = *pa;
delete pa;//bingo
A a(ra);
IlushaMax, вопрос
Цитата Сообщение от IlushaMax Посмотреть сообщение
не лучше ли сделать так?:
нужно объяснить компилятору. Конструктор копирования ищется по сигнатуре и нужен при различных случаях, таких как
передача/возврат, например.
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
26.06.2018, 01:47 7
IGPIGP, только вот в твоём коде &ra!=nullptr

А вот
A& ref = *((A)nullptr); уже UB и сегфолт зачастую. А значит, в мало-мальско сносном коде ссылка точно никогда не будет указывать на nullptr, о чём писали выше.

Добавлено через 3 минуты
shmkv, твой код — UB, такого не должно быть.

А вот то, что в указателе может быть nullptr, стандартом допускается.
0
4004 / 3266 / 914
Регистрация: 25.03.2012
Сообщений: 12,200
Записей в блоге: 1
26.06.2018, 03:56 8
Цитата Сообщение от shmkv Посмотреть сообщение
C++
1
2
T *p = nullptr;
f(*p);
Никакой null в конструктор не пропихнули. Ошибка появляется ДО его пропихивания.
во второй строчке вообще два разных действия.
Сначала происходит UB когда ломается с UB вычисление выражения в скобках, потом идёт собственно вызов, который не ответственнен за поломку.

Не по теме:

потом идёт - некорректно так говорить, но смысл ясен


всё равно что обвинить автора функции foo в том, что не предусмотрел ошибку с отрицательным значением аргумента
C++
1
foo( sqrt(-1) );
0
Комп_Оратор)
Эксперт по математике/физике
8789 / 4544 / 612
Регистрация: 04.12.2011
Сообщений: 13,549
Записей в блоге: 16
26.06.2018, 09:39 9
Цитата Сообщение от New man Посмотреть сообщение
IGPIGP, только вот в твоём коде &ra!=nullptr
Конечно. Только nullptr переданный с указателем это меньшее из зол. Такой указатель нельзя разыменовывать, но можно проверить на равенство nullptr. А вот указатель инициализированный чем попало или содержащий невалидный адрес проверить, мягко говоря, также просто как и дохлую ссылку. Моя реплика была не о nullptr, а о том, что безопасность ссылки по сравнению с указателем несколько преувиличена. И главное, не имеет отношения к теме о конструкторах копирования.
Кроме всего. Если вы так уж хотите буквальных и не требующих размышлений ответов то извольте:
C++
1
2
3
4
5
A* pa = new A();
A& ra = *pa;
//delete pa;//bingo
pa=nullptr;
A a(ra);
Это не значит, что ссылка указывает на nullptr. Но и указатель который содержит значение nullptr тоже неизвестно куда указывает. Главное, что адрес не валиден.
0
Эксперт С++
8720 / 4300 / 958
Регистрация: 15.11.2014
Сообщений: 9,744
26.06.2018, 10:23 10
функция, которая по смыслу должна принимать
только живой валидный объект не должна допускать
даже намёка на то, что объект может быть не валиден.
такая функция принимает по ссылке,
закладываясь, что ссылка априори валидная.

ситуация, когда функции, которая ожидает валидный обьект,
а ей скормили инвалида - программная ошибка в логике.
в этом случае нужно дебажить/править код,
а не изобретать костыли аля проверки указателя на нуль.

зы: ошибок с протухшими указателями больше,
чем с протухшими ссылками
0
Комп_Оратор)
Эксперт по математике/физике
8789 / 4544 / 612
Регистрация: 04.12.2011
Сообщений: 13,549
Записей в блоге: 16
26.06.2018, 12:09 11
Цитата Сообщение от hoggy Посмотреть сообщение
зы: ошибок с протухшими указателями больше,
чем с протухшими ссылками
Кто же спорит? Однако, сигнатура конструктора копии (не перемещающего, а то совсем утонем), это контракт вшитый в язык. То что, в этом была какая-то логика (надеть подгузники на взрослых мужиков и получить невозможность отложенной инициализации с последствиями в виде невозможности создания массивов ссылое например) это бесспорно. Но вопрос топика:
Цитата Сообщение от IlushaMax Посмотреть сообщение
не лучше ли сделать так?:
И ответ - не лучше, потому, что это просто, не будет работать как конструктор копии. Может я не понял вопрос?
0
1369 / 513 / 71
Регистрация: 21.07.2015
Сообщений: 1,298
26.06.2018, 12:18 12
Цитата Сообщение от New man Посмотреть сообщение
shmkv, твой код — UB, такого не должно быть.
А разыменование нулевого указателя в коде функции не UB? Или будем обсуждать какое UB более UB? На практике мне приходится разбирать больше число дампов как с невалидными указателями, так и с ссылками. Но ссылки все же предпочтительнее т. к. могут защитить от неправильного использования. Но от ошибок в логике никакой защиты они не дают.

Добавлено через 2 минуты
Цитата Сообщение от New man Посмотреть сообщение
А значит, в мало-мальско сносном коде ссылка точно никогда не будет указывать на nullptr
Весьма громкое заявление.

Добавлено через 3 минуты
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Сначала происходит UB когда ломается с UB вычисление выражения в скобках, потом идёт собственно вызов, который не ответственнен за поломку.
Даже объяснять лениво, да и, видимо, бесполезно. IGPIGP вижу попытался.
1
Эксперт С++
8720 / 4300 / 958
Регистрация: 15.11.2014
Сообщений: 9,744
26.06.2018, 12:18 13
Цитата Сообщение от shmkv Посмотреть сообщение
Весьма громкое заявление.
норма жизни
0
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
26.06.2018, 12:28 14
Прелесть конструктора копирования в том, что он используется в стандартной библиотеке для работы с контейнерами. Также с ним работают некоторые оптимизации компилятора.

Определить конструктор для указателя можно, но возможно, стоит просто разыменовывать указатель перед передачей в конструктор.
0
Комп_Оратор)
Эксперт по математике/физике
8789 / 4544 / 612
Регистрация: 04.12.2011
Сообщений: 13,549
Записей в блоге: 16
26.06.2018, 12:40 15
Цитата Сообщение от Mirmik Посмотреть сообщение
Прелесть конструктора копирования в том, что он используется в стандартной библиотеке для работы с контейнерами.
Он вообще говоря в функциях используется, а так же при явном вызове копирования. В том числе при инициализации присваиванием. Прелестей у него много.
А вот у константной ссылки есть прелесть которая позволяет передавать объекты на которые нельзя взять адрес. В этом их преимущество и... ржавый и гнутый гвоздь:
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
#include <iostream>
#include <string>
using namespace std;
string where = "none";
struct IntAble
    {
        int a;
 
        IntAble(int a_=0):a(a_){
            cout<<"greatings from: "<<where<<" I am ctor and I can throw!"<<endl;       
        where = "none";
        }
 
    };
 
void foo(const IntAble & a){    
cout<<a.a<<endl;
}
void foo(const IntAble * a){    
cout<<a->a<<endl;
}
int main(int argc, char* argv[])
{
    where = "foo &";
foo(123);
 
where = "main";
IntAble a=234;//тут можно поймать
    where = "foo *";
foo(&a);//а тут его не будет
cout<<endl;
system("pause");
return 0;
}
0
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
26.06.2018, 12:49 16
Хорошее замечание. Конструктор копирования может работать с временными объектами без черной магии, в отличи от конструктора с параметром-указателем.
1
Комп_Оратор)
Эксперт по математике/физике
8789 / 4544 / 612
Регистрация: 04.12.2011
Сообщений: 13,549
Записей в блоге: 16
26.06.2018, 13:21 17
Цитата Сообщение от Mirmik Посмотреть сообщение
Конструктор копирования может работать с временными объектами без черной магии
А указатели с ними просто не работают. Вне зависимости от магии неявных преобразований, вызываемой ссылками на приведения. Но я имел ввиду не это. Я имел ввиду тот простой факт, что передача указателя гарантирует отсутствие исключения на вызываемой стороне, вызванного конструированием (бошенного из конструктора).
1
Неэпический
17807 / 10579 / 2042
Регистрация: 27.09.2012
Сообщений: 26,609
Записей в блоге: 1
26.06.2018, 14:20 18
Лучший ответ Сообщение было отмечено Kuzia domovenok как решение

Решение

Цитата Сообщение от shmkv Посмотреть сообщение
T *p = nullptr;
f(*p);//undefined behavior
There shall be no references to references, no arrays of references, and no pointers to references. The declaration of a reference shall contain an initializer (11.6.3) except when the declaration contains an explicit extern specifier (10.1.1), is a class member (12.2) declaration within a class definition, or is the declaration of a parameter or a return type (11.3.5); see 6.1. A reference shall be initialized to refer to a valid object or function. [ Note: In particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by indirection through a null pointer, which causes undefined behavior. As described in 12.2.4, a reference cannot be bound directly to a bit-field. — end note ]
Программы, которые не well-defined обсуждать нет смысла.
Цитата Сообщение от IlushaMax Посмотреть сообщение
не лучше ли сделать так?
Это уже не будет являться конструктором копирования.
Конструктор копирования - это конструктор у которого первый параметр lvalue-ссылка на объект этого же класса, а остальные параметры заданы по-умолчанию, либо отсутствуют. То есть для типа Some, конструктор копирования может выглядеть как-то так так:
C++
1
2
3
4
Some(Some &);//Один параметр
Some(Some const &);//Один параметр
Some(Some const &, int = 10, double = 33.9);//Несколько параметров, но все кроме первого заданы по-умолчанию.
//...
2
0 / 0 / 4
Регистрация: 09.04.2016
Сообщений: 128
26.06.2018, 15:42  [ТС] 19
То-есть если у меня есть класс Class и конструктор
C++
1
2
3
4
имяКласса (const имяКласса & object)
{
    //код конструктора копирования
}
Class class1;
Class *class2;
Я могу вызвать Class(class1); и Class(class2); и получу одно и тоже?
Извиняюсь, уже понял, просто мой первый ооп язык - java, ещё не привык
Там он скорее такой
C++
1
2
3
4
имяКласса (имяКласса * object)
{
    //код конструктора копирования
}
0
1369 / 513 / 71
Регистрация: 21.07.2015
Сообщений: 1,298
26.06.2018, 15:53 20
Цитата Сообщение от IlushaMax Посмотреть сообщение
и получу одно и тоже?
Второй вариант вообще не скомпилируется.

Добавлено через 37 секунд
Цитата Сообщение от Croessmah Посмотреть сообщение
Программы, которые не well-defined обсуждать нет смысла.
Согласен, но с этого и началось обсуждение.
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.06.2018, 15:53
Помогаю со студенческими работами здесь

Создать класс "Вектор" и реализовать конструктор по умолчанию, конструктор копирования и деструктор
Всем доброго времени суток! нужна ваша помощь! нужно создать класс вектор и реализовать...

Конструктор копирования
Выдераю кусок кода с программы надеюсь поймете кто будет смотреть: конструктор: myclass(const...

Конструктор копирования
Почему экземпляры класса копируются без конструктора копий ? и к тому же получили разные адреса ?...

Конструктор копирования
Есть вопрос. Как объект одного класса передать в объект другого класса?


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru