Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Что происходит ? / 23 сообщений из 23, страница 1 из 1
29.03.2019, 13:29
    #39793551
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
struct T {
   int a;
}


T getT() {
    T t{};
    return t;
}


void main() {
  T t = getT(); // Что произошло c результатом getT() здесь ?
  std::cout << t.a << std::endl;


  getT(); // Что произошло c результатом getT() здесь ?
  T t1 = getT(); // Что произошло c результатом getT() здесь ?
  std::cout << t1.a << std::endl;

}
...
Рейтинг: 0 / 0
29.03.2019, 13:52
    #39793570
Cerebrum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Код: plaintext
1.
T t = getT();


возврат копии структуры по значению. Возможно при использовании оптимизации компилятор применит RVO и сократит ряд копирований/разружений. В этом случае лучше определить перемещающий конструктор и использовать std::move, чтобы гарантировано избежать подобных неоднозначностей.

В данном случае возвращаемое значение (rvalue) улетает в никуда
Код: plaintext
1.
getT();
...
Рейтинг: 0 / 0
29.03.2019, 14:03
    #39793585
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Cerebrum
Код: plaintext
1.
T t = getT();


возврат копии структуры по значению. Возможно при использовании оптимизации компилятор применит RVO и сократит ряд копирований/разружений. В этом случае лучше определить перемещающий конструктор и использовать std::move, чтобы гарантировано избежать подобных неоднозначностей.

В данном случае возвращаемое значение (rvalue) улетает в никуда
Код: plaintext
1.
getT();




T t = std::move(getT());

?
...
Рейтинг: 0 / 0
29.03.2019, 14:04
    #39793586
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
--В данном случае возвращаемое значение (rvalue) улетает в никуда

В никуда это не ответ


Что происходит ?
...
Рейтинг: 0 / 0
29.03.2019, 14:05
    #39793587
Cerebrum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
...
Рейтинг: 0 / 0
29.03.2019, 14:10
    #39793590
Cerebrum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
semen.s.semen--В данном случае возвращаемое значение (rvalue) улетает в никуда

В никуда это не ответ
Что происходит ?

getT возвращает значение которое никто не принимает, следовательно тут будет все зависеть от компилятора
Если сборка производится с оптимизирующими флагами и внутри getT никто не выделяет память из кучи, то компилятор скорее всего вообще удалит данный вызов, как мусорный и не меняющий саму суть кода.

В debug режиме компилятор может создать rvalue копию значения, которая будет разрушена при выходе из области видимости, т.е. }. Но поскольку обратится к ней нет никакой возможности, debug компилятор, может также выкинуть эту инструкцию, просто вызовет getT, но возвращаемое значение соптимизирует.
...
Рейтинг: 0 / 0
29.03.2019, 14:13
    #39793592
Cerebrum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
...
Рейтинг: 0 / 0
29.03.2019, 14:18
    #39793601
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
std::move это страшная покрытая мраком мгла - которая ничуть не более чем каст

Реально есть память А, есть память B и дальше мы каким то образом переносим данные из одной части в другую

Вот у нас стек

1 <----- зашли в getT()
2 выделили память под T;
3 <------ вышли из getT();

Я так понимаю, что при определенных настройках компилятора - мы заиспользуем прямо ту память которая на стеке была зерезервирована в точке 2

Однако при выходе из метода ее уже может не существовать (все таки стек)

Вот и хочется понять экспертизу данного поведения

При каких ключиках и настройках (или других факторах) мы получим адрес ровной той памяти что выделилась на стеке внутри метода - а при каких на стеке создадут копию и как то переместят туда ранее созданное в методе добро (как это будут делать при помощи std::move или copy конструктора) - дело десятое.
...
Рейтинг: 0 / 0
29.03.2019, 14:23
    #39793609
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
semen.s.semenВот и хочется понять экспертизу данного поведения

Ну так --save-temps в руки и смотри на порождаемый ассемблер до просветления.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
29.03.2019, 14:40
    #39793624
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
semen.s.semenstd::move это страшная покрытая мраком мгла - которая ничуть не более чем каст

Реально есть память А, есть память B и дальше мы каким то образом переносим данные из одной части в другую

Вот у нас стек

1 <----- зашли в getT()
2 выделили память под T;
3 <------ вышли из getT();
...

Может так быть:
1 выделили память под T;
2 <----- зашли в getT()
3 <------ вышли из getT();

Со стеком полный порядок.
...
Рейтинг: 0 / 0
29.03.2019, 15:06
    #39793656
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Dimitry Sibiryakovsemen.s.semenВот и хочется понять экспертизу данного поведения

Ну так --save-temps в руки и смотри на порождаемый ассемблер до просветления.


Ох уж эти RTFM и поди погугли эксперты :)

Хочется информации от умных людей )
...
Рейтинг: 0 / 0
29.03.2019, 15:08
    #39793662
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Cerebrum,

спасибо


извиняюсь если был грубоват - характер.
...
Рейтинг: 0 / 0
29.03.2019, 15:14
    #39793675
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Копирование происходит в данном случае
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
T getT() {
	T t{};
	printf("%p getT()\n", &t);
	return t;
};


void test_T() {
	T t = getT(); // Что произошло c результатом getT() здесь ?
	printf("%p test_T()\n", &t);
};


Выводит
Код: plaintext
1.
000000000030FEE0 getT()
000000000030FEE4 test_T()

MSVC 2017
...
Рейтинг: 0 / 0
29.03.2019, 15:28
    #39793693
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Dima Tsemen.s.semenstd::move это страшная покрытая мраком мгла - которая ничуть не более чем каст

Реально есть память А, есть память B и дальше мы каким то образом переносим данные из одной части в другую

Вот у нас стек

1 <----- зашли в getT()
2 выделили память под T;
3 <------ вышли из getT();
...

Может так быть:
1 выделили память под T;
2 <----- зашли в getT()
3 <------ вышли из getT();

Со стеком полный порядок.

Теоретически таких T внутри метода может быть масса

Заранее выделить в стеке не получится
...
Рейтинг: 0 / 0
29.03.2019, 15:48
    #39793715
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
semen.s.semenDima Tпропущено...


Может так быть:
1 выделили память под T;
2 <----- зашли в getT()
3 <------ вышли из getT();

Со стеком полный порядок.

Теоретически таких T внутри метода может быть масса

Заранее выделить в стеке не получится
Почему? ИМХО это просто шаманство на уровне компиляции, компилятор видит весь код и в разных случаях один и тот же код getT() скомпилирует по-разному.

Своими словами мне сложно объяснить, в этой книге неплохо описаны принципы работы std::move
...
Рейтинг: 0 / 0
29.03.2019, 15:58
    #39793721
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Да причем тут вообще std::move
...
Рейтинг: 0 / 0
29.03.2019, 15:59
    #39793724
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Dima TСвоими словами мне сложно объяснить

Это говорит об отсутствии четкого и ясного понимания и экспертизы
...
Рейтинг: 0 / 0
29.03.2019, 16:10
    #39793733
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
semen.s.semenDima TСвоими словами мне сложно объяснить

Это говорит об отсутствии четкого и ясного понимания и экспертизы
Я с std::move не разбирался, как понял он и так работает в stl.

А данном коде просто копирование происходит. Может код понятнее будет если заменить T на int. Разницы никакой.
...
Рейтинг: 0 / 0
29.03.2019, 17:32
    #39793806
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Код: plaintext
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.
#include <iostream>

struct A {
public:
  void t() {}

  A() {}

  A(A &t) { std::cout << "std::copy" << std::endl; }

  A(A &&t) { std::cout << "std::move" << std::endl; }

  A &operator=(A &&data) noexcept {}
};

void point(A t) {}

A getA() {
  A a{};
  return a;
}

int main() {
  // A a{};
  // point(std::move(a));
  // A b = std::move(a);

  A a = getA();

  a.t();
}
...
Рейтинг: 0 / 0
29.03.2019, 17:33
    #39793808
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Код: plaintext
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.
#include <iostream>

struct A {
public:
  void t() {}

  A() {}

  A(A &t) { std::cout << "std::copy" << std::endl; }

  A(A &&t) { std::cout << "std::move" << std::endl; }

  A &operator=(A &&data) noexcept {}
};

void point(A t) {}

A& getA() {
  A a{};
  return a;
}

int main() {
  // A a{};
  // point(std::move(a));
  // A b = std::move(a);

  A a = getA();

  a.t();
}
...
Рейтинг: 0 / 0
29.03.2019, 17:46
    #39793833
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
semen.s.semen,

Вызывающий код выделяет память в стеке под возвращаемое значение и передает его адрес в функцию вместе с аргументами (адрес не всегда нужно передавать явно, например если память выделить на верхушке стека, то вызывающая функция может адрес рассчитать; это все зависит от реализации).
Вызванная функция создает объект в этой памяти.
Вызывающий код пользуется этим объектом, потом вызывает для него деструктор и освобождает память - при выходе из области видимости.

Если функция вызывается без присвоения в переменную, то происходит все тоже самое, только переменная не видна программисту и освобождается после вызова.

Все вышеописанное происходит в любом случае даже без оптимизаций.

Есть еще оптимизация RVO.
Если внутри функции создается переменная, которая потом возвращается, то компилятор имеет право не создавать отдельную переменную и потом копировать ее в возвращаемое значение, а создать эту переменную сразу в памяти выделенной под возвращаемое значение.
...
Рейтинг: 0 / 0
29.03.2019, 17:52
    #39793843
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Поправка, то что я описал - это NRVO.
А RVO работает на вызывающей стороне, когда возвращаемое значение создается в переменной куда присваивается, а не во временной с копированием в переменную.
...
Рейтинг: 0 / 0
29.03.2019, 17:53
    #39793844
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит ?
Anatoly Moskovskysemen.s.semen,

Вызывающий код выделяет память в стеке под возвращаемое значение и передает его адрес в функцию вместе с аргументами (адрес не всегда нужно передавать явно, например если память выделить на верхушке стека, то вызывающая функция может адрес рассчитать; это все зависит от реализации).
Вызванная функция создает объект в этой памяти.
Вызывающий код пользуется этим объектом, потом вызывает для него деструктор и освобождает память - при выходе из области видимости.

Если функция вызывается без присвоения в переменную, то происходит все тоже самое, только переменная не видна программисту и освобождается после вызова.

Все вышеописанное происходит в любом случае даже без оптимизаций.

Есть еще оптимизация RVO.
Если внутри функции создается переменная, которая потом возвращается, то компилятор имеет право не создавать отдельную переменную и потом копировать ее в возвращаемое значение, а создать эту переменную сразу в памяти выделенной под возвращаемое значение.

Спасибо за ясную экспертизу
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Что происходит ? / 23 сообщений из 23, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]