Возврат по значению и копирующий конструткор
От: Vamp Россия  
Дата: 13.10.05 10:13
Оценка:
Вот простой пример:
class A {
    A();
    A(const A&);
public:
    A(int ) {}
};

A foo() {
    return A(10);
} 

int main() {
} //foo is never called!

Пример компилироваться не будет, потому что компилятор потребует копирующий конструктор, который недоступен. Но вот так подумать, зачем компилятору в этом случае копирующий конструктор? Какие промежуточные объекты создаютя в этом случае?
Да здравствует мыло душистое и веревка пушистая.
Re: Возврат по значению и копирующий конструткор
От: Pavel Dvorkin Россия  
Дата: 13.10.05 10:19
Оценка:
Здравствуйте, Vamp, Вы писали:

V>} //foo is never called!


Это он здесь never called. А в другом файле проекта у тебя

_extern A a;
a.foo();

А компилятор файлы компилирует каждый по отдельности.
With best regards
Pavel Dvorkin
Re: Возврат по значению и копирующий конструткор
От: Poirot Россия  
Дата: 13.10.05 10:20
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Вот простой пример:

V>
V>class A {
V>    A();
V>    A(const A&);
V>public:
V>    A(int ) {}
V>};

V>A foo() {
V>    return A(10);
V>} 

V>int main() {
V>} //foo is never called!

V>

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

Ну как минимум он нужен в return — вернее сам процесс возвращения значения... еслибы была ссылка — всё бы было хорошо. читаем Трупа Страуса_
Re: Возврат по значению и копирующий конструткор
От: 0xDEADBEEF Ниоткуда  
Дата: 13.10.05 10:26
Оценка: 1 (1)
Здравствуйте, Vamp, Вы писали:

V>Пример компилироваться не будет, потому что компилятор потребует копирующий конструктор,

V>который недоступен.
...Так требует стандарт (всем прикрыть глаза и благоговейно сказать о-о-о-о).

V>Но вот так подумать, зачем компилятору в этом случае копирующий конструктор?

V>Какие промежуточные объекты создаютя в этом случае?
Дело в том, что стандарт допускает (но не требует) для этого случая оптимизацию
"constructor eliding" (поищи в стандарте слово elide).

То есть, если предположить, что конструктор копирования не требуется,
все будет работать, в случае, если компилятор выполняет "constructor eliding".
Но, с другой стороны, если компилятор этой оптимизации не выполняет, то работать это дело не будет...
Так что, стандарт рассчитывает на худший случай и мне кажется это есть хорошо.
__________
16.There is no cause so right that one cannot find a fool following it.
Re[2]: Возврат по значению и копирующий конструткор
От: Vamp Россия  
Дата: 13.10.05 10:26
Оценка:
PD>Это он здесь never called. А в другом файле проекта у тебя
...
И? Вот при компиляции другой единицы и портебуется тот самый копи-конструктор.
Да здравствует мыло душистое и веревка пушистая.
Re: Возврат по значению и копирующий конструткор
От: srggal Украина  
Дата: 13.10.05 10:29
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Вот простой пример:

V>
V>class A {
V>    A();
V>    A(const A&);
V>public:
V>    A(int ) {}
V>};

V>A foo() {
V>    return A(10);
V>} 

V>int main() {
V>} //foo is never called!

V>

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

Промежуточный объект ДОЛЖЕН создаваться, но его создание может быть позднее соптимизировано.
Ключевой момент — позднее.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: Возврат по значению и копирующий конструткор
От: jazzer Россия Skype: enerjazzer
Дата: 13.10.05 10:31
Оценка: 3 (1)
Здравствуйте, Vamp, Вы писали:

V>Вот простой пример:

V>
V>class A {
V>    A();
V>    A(const A&);
V>public:
V>    A(int ) {}
V>};

V>A foo() {
V>    return A(10);
V>} 

V>int main() {
V>} //foo is never called!

V>


То, что foo is never called, ничего не значит: она вполне может быть called из другой единицы трансляции.
Так что компилятор совершенно прав, компилируя foo.

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


Потому что у него так организована работа со стеком. Например, создается временный объект в кадре стека функции foo, а потом зовется конструктор копирования для принимающего объекта в кадре вызывающей функции.
Компилятору так удобнее, и Стандарт это разрешает.
Вот когда Стандарт скажет, что RVO обязательно к выполнению и тем самым упразднит обязательный вызов копиктора — тогда да.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Возврат по значению и копирующий конструткор
От: Vamp Россия  
Дата: 13.10.05 10:35
Оценка:
P>Ну как минимум он нужен в return — вернее сам процесс возвращения значения... еслибы была ссылка — всё бы было хорошо. читаем Трупа Страуса_
Так в том и состоит вопрос — зачем он в return?
Да здравствует мыло душистое и веревка пушистая.
Re[3]: Возврат по значению и копирующий конструткор
От: jazzer Россия Skype: enerjazzer
Дата: 13.10.05 10:36
Оценка:
Здравствуйте, Vamp, Вы писали:

PD>>Это он здесь never called. А в другом файле проекта у тебя

V>...
V>И? Вот при компиляции другой единицы и портебуется тот самый копи-конструктор.

ну код-то foo у тебя в первой единице трансляции и именно там он и будет лежать.
а в другой просто будет ссылка, которой займется линкер
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Возврат по значению и копирующий конструткор
От: Vamp Россия  
Дата: 13.10.05 10:44
Оценка:
DEA>Дело в том, что стандарт допускает (но не требует) для этого случая оптимизацию
DEA>"constructor eliding" (поищи в стандарте слово elide).
Я так понимаю, что "constructor eliding" это нечто другое.
Я его понимаю так:
A a = foo(); -- вот здесь "constructor eliding" минует промежуточный копи-ктор из временного объекта в a. В моем случае я не понимаю, зачем что-то куда-то перекладывать. Почему функция не может создать свой объект сразу там, где он будет возвращен в вызывающий фрейм.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Возврат по значению и копирующий конструткор
От: Vamp Россия  
Дата: 13.10.05 10:44
Оценка:
S>Промежуточный объект ДОЛЖЕН создаваться, но его создание может быть позднее соптимизировано.
Почему? Зачем?
Да здравствует мыло душистое и веревка пушистая.
Re[3]: Возврат по значению и копирующий конструткор
От: srggal Украина  
Дата: 13.10.05 10:49
Оценка:
Здравствуйте, Vamp, Вы писали:

S>>Промежуточный объект ДОЛЖЕН создаваться, но его создание может быть позднее соптимизировано.

V>Почему? Зачем?

Чуть раньше ( я этого не успел увидеть ) ответ дал 0xDEADBEEF здесь
Автор: 0xDEADBEEF
Дата: 13.10.05


Дело в том, что стандарт допускает (но не требует) для этого случая оптимизацию
"constructor eliding" (поищи в стандарте слово elide).


Т.е. в том случае если приведенный Вами код будет компилироваться на компиляторе, который такую оптимизацию не производит ( имеет право см. выше ), то код будет некорректным, т.е. налицо дуализм — код и компилируется (на одном типе компиляторов) и не компилируется ( на другом ) , поэтому оптимизирующие подобный код компиляторы и требуют конструктора копирования, дабы прсечь дуализм.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[3]: Возврат по значению и копирующий конструткор
От: srggal Украина  
Дата: 13.10.05 10:53
Оценка:
Здравствуйте, Vamp, Вы писали:

Почему функция не может создать свой объект сразу там, где он будет возвращен в вызывающий фрейм.

class A {
    A();
    A(const A&);
public:
    A(int ) {}        

        int GetInt();

};

A foo() {

    A a;
    ...
    // some action with a
    ...    
    return a;

} 

int main() {

    std::cout << foo().GetInt() << std::endl;
} //foo is never called!


Что где создавать?
Чему будет возвращено Если делать так как Вы говорите ?
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[4]: Возврат по значению и копирующий конструткор
От: Vamp Россия  
Дата: 13.10.05 10:56
Оценка:
S>
S>A foo() {
S>
S>    A a;
S>    ...
S>    // some action with a
S>    ...    
S>    return a;
S>
S>} 
S>


Это ведь не мой пример, правда? Речь шла про функцию в том виде, в котором она написана в моем случае.
Да здравствует мыло душистое и веревка пушистая.
Re[5]: Возврат по значению и копирующий конструткор
От: srggal Украина  
Дата: 13.10.05 11:02
Оценка:
Здравствуйте, Vamp, Вы писали:

S>>
S>>A foo() {
S>>
S>>    A a;
S>>    ...
S>>    // some action with a
S>>    ...    
S>>    return a;
S>>
S>>} 
S>>


V>Это ведь не мой пример, правда? Речь шла про функцию в том виде, в котором она написана в моем случае.


Вы писали, чуть выше:

A a = foo(); -- вот здесь "constructor eliding" минует промежуточный копи-ктор из временного объекта в a. В моем случае я не понимаю, зачем что-то куда-то перекладывать. Почему функция не может создать свой объект сразу там, где он будет возвращен в вызывающий фрейм.


Именно не Ваш, поэтому и есть "constructor eliding" дабы не анализировать случай, приведенный мной
ИМХО: Благо он легко решается "constructor eliding" и не требует дополнительной логики.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: Возврат по значению и копирующий конструткор
От: FoolS.Top Армения  
Дата: 13.10.05 11:14
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Вот простой пример:

V>
V>class A {
V>    A();
V>    A(const A&);
V>public:
V>    A(int ) {}
V>};

V>A foo() {
V>    return A(10);
V>} 

V>int main() {
V>} //foo is never called!

V>

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

Копирующий конструктор используется для создания возвращаемого значения.



"Как и передача аргументов, семантика возврата значения из функции идентична семантике инициализации."

Б. Страуструп
C++ ...., 7.3, стр.190

Feierlich, misterioso
Re[3]: Возврат по значению и копирующий конструткор
От: Шахтер Интернет  
Дата: 13.10.05 11:24
Оценка:
Здравствуйте, Vamp, Вы писали:

S>>Промежуточный объект ДОЛЖЕН создаваться, но его создание может быть позднее соптимизировано.

V>Почему? Зачем?

Такова была изначальная семантика return. Разумеется, можно было бы вернуть объект вызовом его конструктора, но реализация этой фичи требует изменений в языке -- нужно вводить альтернативный оператор возврата коструированием, а не копированием.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: Возврат по значению и копирующий конструткор
От: Vamp Россия  
Дата: 13.10.05 11:51
Оценка:
Ш>Такова была изначальная семантика return.

То есть, все упирается в чисто исторические причины?
Да здравствует мыло душистое и веревка пушистая.
Re[5]: Возврат по значению и копирующий конструткор
От: Шахтер Интернет  
Дата: 13.10.05 11:54
Оценка:
Здравствуйте, Vamp, Вы писали:

Ш>>Такова была изначальная семантика return.


V>То есть, все упирается в чисто исторические причины?


Да.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Возврат по значению и копирующий конструткор
От: srggal Украина  
Дата: 13.10.05 13:07
Оценка:
Здравствуйте, Vamp, Вы писали:
Ещё один пример, аналогичный Вашему
Re: Момент вызова деструктора при throw
Автор: jazzer
Дата: 13.10.05
... << RSDN@Home 1.1.4 stable rev. 510>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.