LINUX.ORG.RU

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


0

0

Хотелось бы разобраться со следующим вопросом:
есть вот такой вот пример:
struct INT
{ };

struct LP
{
LP(const INT &p);
LP& operator=(const INT &p);
};

struct P
{
operator INT ();
};

int main()
{
P pi1;
LP lpi2(pi1); // OK
LP lpi2_ = pi1; // FAILS!
lpi2 = pi1; // OK
}

в строке // FAILS! компилятор выдает ошибку "error: conversion from 'P' to non-scalar type 'LP' requested". Т.е. такая конструкция для g++ похоже имеет другой от (LP lp2(pi1)) смысл. Подскажите плз, в чем здесь проблема? И как то можно ее решить, чтобы эта строка была съедобной для g++?


Можбыть, потому, что

> LP lpi2_ = pi1; // FAILS!

слегка конструктор копий? Счас проверю...

one_more_hokum ★★★
()
Ответ на: комментарий от one_more_hokum

> LP lpi2_ = (INT)pi1;

> Не?

Можно и так, и эдак. Просто не принято использовать приведение типов в таком виде. Или static_cast<INT>(pi1), или INT(pi1). Хотя это уже почти холивар получается :)

const86 ★★★★★
()
Ответ на: комментарий от const86

> не принято использовать приведение типов в таком виде

Ну да, типизация в плюсах доставляет и оставляет желать лучшего. :-) Так, можбыть, замутим holywar страниц на стопицот?

one_more_hokum ★★★
()
Ответ на: комментарий от const86

И я всё-таки не понимаю, почему даже при наличии оператора преобразования конструктор копий (сгенерированный автоматически компилятором) не использовал его?

one_more_hokum ★★★
()
Ответ на: комментарий от dilmah

Вообще, в The C++ Programming Language (3rd Edition) by Bjarne Stroustrup
в секции 11.4.1 [over.ambig] написано, что (в переложении на наш случай):

An assignment of a value of type P to an object of class LP is legal if there is
an assignment operator LP::operator=(INT) so that P is INT or there is a unique
conversion of P to INT. Initialization is treated equivalently.

Насколько я понимаю, у нас
    LP lpi2_ = pi1; // Initialization.
    lpi2 = pi1; // Assignment.

Поэтому, в соответствии с "Initialization is treated equivalently.", всё должно
работать, чего мы не наблюдаем.

ptomaine
()
Ответ на: комментарий от www_linux_org_ru

> Насколько я понимаю, это ни разу не инициализация, а присваивание.

Не-а! Объявление переменной на одной строке с присвоением = вызов конструктора копий.

one_more_hokum ★★★
()
Ответ на: комментарий от one_more_hokum

> Не-а! Объявление переменной на одной строке с присвоением = вызов конструктора копий.

Хорошо, разберемся:

1. "A a=b" и "a=b" вызывают одинаковые конструкторы A(const B&), да?

2. И если A и В один и тот же класс, ничего не меняется?

www_linux_org_ru ★★★★★
()

Во втором случае должно вызваться LP(P&) и потом скопироваться. Читать стандарт пункт 12.6.1.

Reset ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> 1. "A a=b" и "a=b" вызывают одинаковые конструкторы A(const B&), да?

нет, в случае "a=b" никаких конструкторов вызываться не будет, это операция присваивания.

A a=b эквивалентно A a(A(b))

Reset ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> 2. И если A и В один и тот же класс, ничего не меняется?

меняется, в этом случае запись "A a=b" будет эквивалентна "A a(b)"

Reset ★★★★★
()
Ответ на: комментарий от Reset

Интересный ответ я получил на забугорном форуме: "This is not allowed by the current C++ standards. To use an implicit copy constructor, such as you are doing ,where the value on the RHS of the assignment is a type which has to be used to construct a temporary of the class you are trying to copy, is not allowed. IE:

LP lpi2(pi1);

is allowed, as you are not using the assignment operator. as is this:

LP lpi2_ = LP(pi1);

as you are constructing an LP object explicitly, But,

LP lpi2_ = pi1;

is not allowed. The gnu compilers are very standards-aware these days, and this will, as you have seen, generate an error."

sotlef
() автор топика
Ответ на: комментарий от sotlef

Ну дык о чем я и говорю. В общем читай пункт 12.6.1 стандарта до просветления.

Reset ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.