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

Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 5.00
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
08.09.2013, 14:08     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #1
Друзья! Вот корректный код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class foo
{
public:
                foo()
                    { 
                    }
                foo(int x)
                    { 
                    }
                ~foo(){}
};
 
 
//+++++++++++++++++++++++++++++++++++++
 
int main()
{
    foo c2 = foo (9);
}
А вот некорректный:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class foo
{
public:
                foo()
                    { 
                    }
                foo(int x)
                    { 
                    }
                foo(foo& f)
                    { 
                    }
                ~foo(){}
};
 
 
//+++++++++++++++++++++++++++++++++++++
 
int main()
{
    foo c2 = foo (9);
}
Ошибки,

Bash
1
2
3
4
5
6
7
8
9
10
main_p.cpp: In function 'int main()':
main_p.cpp:21:20: error: no matching function for call to 'foo::foo(foo)'
main_p.cpp:21:20: note: candidates are:
main_p.cpp:10:17: note: foo::foo(foo&)
main_p.cpp:10:17: note:   no known conversion for argument 1 from 'foo' to 'foo&'
main_p.cpp:7:17: note: foo::foo(int)
main_p.cpp:7:17: note:   no known conversion for argument 1 from 'foo' to 'int'
main_p.cpp:4:17: note: foo::foo()
main_p.cpp:4:17: note:   candidate expects 0 arguments, 1 provided
Выполнение завершено
первая же из которых вводит в ступор. У меня нет вызова foo::foo(foo)! Если бы он был, то первый код не скомпилился бы. В общем, непонятно, почему foo(foo& f) всё портит во втором коде, хотелось бы разъяснений, тык скыть. Спасибо, кто откликнется.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.09.2013, 14:08     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит
Посмотрите здесь:

сегодня наконец то понял что такое КЛАСС, и ОБЪЕКТ. понято всё, кроме одного - зачем всё это? в смысле, можно же без этого? так зачем жизнь усложнять? C++
C++ Конструктор принимающий два целочисленных значения
Функция в качестве аргумента C++
Передача двухмерного массива в качестве аргумента C++
C++ Создать функцию, которая принимает в качестве аргумента ссылку на string, и преобразует все буквы в верхний регистр
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Schizorb
 Аватар для Schizorb
508 / 460 / 16
Регистрация: 07.04.2012
Сообщений: 865
Записей в блоге: 1
Завершенные тесты: 1
08.09.2013, 14:31     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #2
Так должно скомпилиться:
C++
1
foo(const foo& f)
По идее, если компилятор не сделает оптимизацию, то сначала вызовется конструктор для временного объекта, потом уже конструктор копирования. На деле это происходит только с опцией: -fno-elide-constructors (для gcc). А ошибка компиляции есть в любом случае, как то странно.
BumerangSP
 Аватар для BumerangSP
4283 / 1405 / 121
Регистрация: 16.12.2010
Сообщений: 2,941
Записей в блоге: 3
08.09.2013, 16:04     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #3
Тут как бы все временные объекты по умолчанию константны. А вместо конструктора, принимающего константную ссылку определен конструктор только не с константной. Можно также это увидеть на примере:
C++
1
2
3
4
5
6
7
8
9
10
11
int main()
{
    const foo c;
    foo c2 = c; // ошибка, нет конструктора, принимающего константную ссылку.
}
//или
int main()
{
    foo c(9);
    foo c2 = c; // все нормально
}
Или вопрос не в этом?
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
08.09.2013, 21:22  [ТС]     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #4

Смотрите, есть код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class foo
{
public:
                foo()
                    { 
                    }
                foo(int x)
                    { 
                    }
                ~foo(){}
};
 
 
//+++++++++++++++++++++++++++++++++++++
 
int main()
{
    foo c2 = foo (9);
}
После добавления в класс конструктора

C++
1
2
3
                foo(foo& f)
                    { 
                    }
появляется ошибка в строке
C++
1
foo c2 = foo (9);
Несмотря на то, что конструктор к этой строке имеет отношение как СВИНЬЯ К АПЕЛЬСИНАМ. Тем не менее, происходит ошибка, почему- не знаю. Почему?
Voivoid
 Аватар для Voivoid
580 / 256 / 12
Регистрация: 31.03.2013
Сообщений: 1,284
08.09.2013, 21:43     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #5
Для создания объекта c2 в первом случае используется конструктор копирования по умолчанию. Во втором же случае используется пользовательский конструктор копирования который принимает неконстантную ссылку, что и приводит к ошибке, ибо на вход ему передается rvalue
BumerangSP
 Аватар для BumerangSP
4283 / 1405 / 121
Регистрация: 16.12.2010
Сообщений: 2,941
Записей в блоге: 3
08.09.2013, 21:44     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #6
kravam, ну так я и говорю: потому что при foo c2 = foo (9); вызывается определенный пользователем копирующий конструктор, принимающий неконстантную ссылку, хотя сам временной объект - константный. Не было б определено копирующего конструктора - он был бы сгенерирован компилятором, но только принимающий константную ссылку.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
08.09.2013, 22:26  [ТС]     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #7
Цитата Сообщение от Voivoid Посмотреть сообщение
Во втором же случае используется пользовательский конструктор копирования который принимает неконстантную ссылку, что и приводит к ошибке, ибо на вход ему передается rvalue
Но я не написал конструктора копирования, как же может использоваться конструктор копирования, которого нет?

Добавлено через 1 минуту
Цитата Сообщение от BumerangSP Посмотреть сообщение
kravam, ну так я и говорю: потому что при foo c2 = foo (9); вызывается определенный пользователем копирующий конструктор, принимающий неконстантную ссылку,
то же самое- нет пользовательского конструктора копирования, не написал я его!
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
08.09.2013, 22:41     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #8
Цитата Сообщение от kravam Посмотреть сообщение
Но я не написал конструктора копирования, как же может использоваться конструктор копирования, которого нет?
Цитата Сообщение от kravam Посмотреть сообщение
foo(foo& f)
это и есть конструктор копирования согласно стандарту с++
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). [ Example: X::X(const X&) and X::X(X&,int=1) are copy constructors.
BumerangSP
 Аватар для BumerangSP
4283 / 1405 / 121
Регистрация: 16.12.2010
Сообщений: 2,941
Записей в блоге: 3
08.09.2013, 23:04     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #9
kravam,
Цитата Сообщение от BumerangSP Посмотреть сообщение
Не было б определено копирующего конструктора - он был бы сгенерирован компилятором, но только принимающий константную ссылку.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
09.09.2013, 20:23  [ТС]     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #10
Цитата Сообщение от Voivoid Посмотреть сообщение
Во втором же случае используется пользовательский конструктор копирования который принимает неконстантную ссылку, что и приводит к ошибке
Вопрос ко всем: я правильно понял, что компилятор хочет использовать КК, находит мой КК
C++
1
foo(foo& f) { }
Но коль скоро он неправилен, то компилятор на него и ругается?

Хотя, между прочим ОН правилен! Он соответствует стандарту- первому образцу из цитаты- ну простоты ради условимся пока, что мой компилятор старенький, gcc 4.6.2, новым стандартам не обучен
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
09.09.2013, 20:26     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #11
Цитата Сообщение от kravam Посмотреть сообщение
Вопрос ко всем: я правильно понял, что компилятор хочет использовать КК, находит мой КК
C++
1
foo(foo& f) { }
Но коль скоро он неправилен, то компилятор на него и ругается?
твой КК правильный с точки зрения с++, но он неправильный с точки зрения твоего использования
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
09.09.2013, 20:27  [ТС]     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #12
Стоп. Если синтаксис моего КК верен, то... то всё. Компилятор должен компильнуть. Но он не компилит, вот в чём дело.

А уж если я его неправильно использую, увидим исключение какое-нибудь во время выполнения программы.
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
09.09.2013, 20:29     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #13
Цитата Сообщение от kravam Посмотреть сообщение
Стоп. Если синтаксис моего КК верен, то... то всё. Компилятор должен компильнуть. Но он не компилит, вот в чём дело.
синтаксис КК верен, но
Цитата Сообщение от kravam Посмотреть сообщение
C++
1
foo c2 = foo (9);
используешь ты его неверно
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
09.09.2013, 20:48  [ТС]     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #14
Цитата Сообщение от Jupiter Посмотреть сообщение
используешь ты его неверно
а как его использовать верно?
BumerangSP
 Аватар для BumerangSP
4283 / 1405 / 121
Регистрация: 16.12.2010
Сообщений: 2,941
Записей в блоге: 3
09.09.2013, 20:50     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #15
kravam, с неконстантными объектами.
Вот аналогичная ситуация:
C++
1
2
3
4
5
6
7
8
9
10
class A
{
public:
    A(int &val) {} // добавить const и все ок 
};
 
int main()
{
    A(10);
}
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
09.09.2013, 20:53  [ТС]     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #16
А какой бы конструктор копирования подошёл для такого кода?
C++
1
foo c2 = foo (9);
Минимальный компилящийся код, пожалуйста. Без наворотов.
BumerangSP
 Аватар для BumerangSP
4283 / 1405 / 121
Регистрация: 16.12.2010
Сообщений: 2,941
Записей в блоге: 3
09.09.2013, 20:56     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #17
C++
1
2
3
4
5
6
7
8
9
10
11
class foo
{
public:
    foo(int x) {}
    foo(const foo& f) {}
};
 
int main()
{
    foo c2 = foo (9);
}
или даже так:
C++
1
2
3
4
5
6
7
8
9
10
class foo
{
public:
    foo(int x) {}
};
 
int main()
{
    foo c2 = foo (9);
}
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
09.09.2013, 20:57     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #18
Вот мое понимание всего этого:
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
class foo
{
public:
   foo() {}
   foo(int x) {}
   foo(foo& f) {}
   ~foo(){}
};
 
int main()
{
   //int& reference = 9;        //Error
   const int& creference = 9; //Ok
 
   //foo& foo_ref = foo(9);       //Error
   const foo& foo_cref = foo(9);//Ok
 
   //foo f = foo(9); //Error: foo(9) есть rvalue; конструктору копий передается
                     //rvalue, а он принимает неконстантную ссылку что не допускается
 
   foo f(9);
   foo& no_const_ref = f; //Ok
   foo f2 = f; //Ok, конструктору копий передается lvalue
   foo f3 = no_const_ref; //Ok
   foo f4 = foo_cref;     //Error
 
   return 0;
}
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
09.09.2013, 21:03  [ТС]     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #19
Что и требовалось доказать. Надеюсь я ничьих чувств не задену, если вставлю сюда отладочную надпись, которую НИКТО НИКОГДА НЕ УВИДИТ?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
class foo
{
public:
    foo(int x) {}
    foo(const foo& f) {printf ("вот её никто никогда не увидит\n");}
};
 
int main()
{
    foo c2 = foo (9);
    getchar ();
}
Так почему же когда я пишу КК, который почему-то использовать нельзя (хотя он синтаксический правильный)- компилятор ругается. Но когда ему подсовываешь тот КК, который можно использовать (почему-то) компилятор его не использует? Фигня какая-то
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.09.2013, 21:39     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит
Еще ссылки по теме:

Использование массивов в качестве аргумента функции C++
Передача символьного массива в качестве аргумента C++
C++ Конструктор, принимающий параметр

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

Или воспользуйтесь поиском по форуму:
Voivoid
 Аватар для Voivoid
580 / 256 / 12
Регистрация: 31.03.2013
Сообщений: 1,284
09.09.2013, 21:39     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит #20
В данном случае компилятор в целях оптимизации избавляется от лишнего вызова конструктора копирования
Yandex
Объявления
09.09.2013, 21:39     Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит
Ответ Создать тему
Опции темы

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