Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/26: Рейтинг темы: голосов - 26, средняя оценка - 4.62
163 / 163 / 68
Регистрация: 23.02.2011
Сообщений: 392
1

"Анонимные" (временные) объекты?

01.08.2012, 19:08. Показов 4787. Ответов 11
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Пусть имеется класс T:
C++
1
2
3
4
5
6
7
class T
{
public:
    int a;
    int b;
    T(int _a, int _b) : a(_a), b(_b) {}
}
Имеется функция
C++
1
2
3
4
void func(T* obj)
{
    std::cout << obj->a << " " << obj->b << std::endl;
}
Здесь в качестве параметра требуется передать указатель на объект, например
C++
1
2
T O(4,2);
func (&O);
Но, если содержимое объекта O после передачи в функцию не представляет интереса, и дабы не загромождать код объявлениями переменных, можно ли передавать в функцию временный(?)
(в Джаве что-то подобное называется анонимным) объект?
C++
1
func(new T(4,2));
Хотя на самом деле, я примеров такой передачи ещё не видел, но проверил, работает
И опять же, в Джаве то сборщик мусора есть, а здесь, увы, неизбежная утечка. Только из-за неё и не юзабельно?
А, ну разве что.
C++
1
2
3
4
5
void func(T* obj)
{
    std::cout << obj->a << " " << obj->b << std::endl;
    delete obj;
}
И кстати, если в такую функцию передать
C++
1
2
T myObj(11,22);
func(&myObj);
то почему delete не освобождает память по ссылке:
C++
1
2
3
func(&myObj);
func(&myObj);
func(&myObj);
Всё выводится ОК.
Ну или же можно использовать
C++
1
func( &T(4,1) );
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.08.2012, 19:08
Ответы с готовыми решениями:

Анонимные объекты
Возник тут у меня совершенно нубский вопрос, даже не знаю как правильно загуглить то. Это...

Необязательные временные объекты
Помогите с задачкой: Класс Car содержит модель автомобиля. Функция Find определяет, присутствует...

Теория, Временные объекты
Прошу ответить на пару вопросов. Конкретный вопрос: В тексте while (Pos !=...

Временные объекты и ссылки
При инициализации ссылки временным объектом, ссылка должна быть либо rvalue-ссылкой, либо...

11
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
01.08.2012, 19:13 2
edward_jonson, убери new в вызове, будет тебе и локальный, и анонимный.
0
163 / 163 / 68
Регистрация: 23.02.2011
Сообщений: 392
01.08.2012, 19:20  [ТС] 3
Vourhey, вместо new - &, как в последней строке моего поста? на это кстати ворнингами ругается компилятор
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
01.08.2012, 19:23 4
Цитата Сообщение от edward_jonson Посмотреть сообщение
вместо new - &, как в последней строке моего поста?
Ну, так как, у тебя функция принимает указатель, то, само собой, амперсанд нужен для взятия адреса. В скобки это все дело, в идеале.

Добавлено через 18 секунд
Цитата Сообщение от edward_jonson Посмотреть сообщение
кстати ворнингами ругается компилятор
по***
1
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
01.08.2012, 19:27 5
Эмм...
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
struct T {
  int a, b;
  T(int a_, int b_) : a(a_), b(b_) {}
};
 
int func(const T &obj)
{
  return obj.a * obj.b;
}
 
int main()
{
  std::cout << func(T(2, 3));
  return 0;
}
Так что ли?
0
163 / 163 / 68
Регистрация: 23.02.2011
Сообщений: 392
01.08.2012, 21:28  [ТС] 6
~OhMyGodSoLong~, не совсем, нужно именно указатель передать
0
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
01.08.2012, 22:15 7
Не, ну тут передаётся ссылка на этот временный объект (фактически, указатель). Без его копирования. Но есть ограничение: этот объект нельзя изменять. И он, конечно же, будет удалён (автоматически) из стека после выполнения функции, куда был передан.

Если именно настоящий указатель с правом изменять содержимое, то у вас всё верно: или (не анонимная) идиома
C++
1
2
3
4
5
T obj(42);
foo(&obj); // void foo(T *obj);
/* но внутри foo никаких delete obj, память
   вам не принадлежит, она очистится автоматом
   при выходе из функции, где это всё происходит */
или
C++
1
2
3
T obj(42);
foo(obj); // void foo(T &obj);
/* железобетонный вариант, но не анонимный */
или
C++
1
2
foo(new T(42)); // void foo(T *obj);
/* теперь внутри foo *надо* не забыть delete obj */
или (не указатель, но технически сойдёт):
C++
1
2
3
foo(T(42)); // void foo(T obj);
/* получаете личную копию, которая
   автоматически удалится из стека */
Но в последнем случае копирование лишнее, эта переменная же временная. В С++11 почили этот недостаток, можно написать
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
struct T {
  int a, b;
  T(int a_, int b_) : a(a_), b(b_) {}
};
 
int func(T &&obj)
{
  obj.a = 10;
  obj.b = 20;
  return a * b;
}
 
int main()
{
  std::cout << func(T(2, 3));
  return 0;
}
И получить, надеюсь, то, что вам надо: объект T создаётся один раз; func получает на него указатель, а не копию; данные объекта можно менять; объект автомагически удалится из стека.
1
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
01.08.2012, 23:26 8
добавлю, что случаи, когда владение объектом нужно передать функции, которая должна будет удалить его, лучше оформлять в виде соответствующих смарт-поинтеров, чтобы явно подчеркнуть факт того, что объект удалится внутри функции. иначе это нужно будет описывать в каментариях, либо лезть в код функции и смотреть, что она делает с простым указателем.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
01.08.2012, 23:49 9
А вот в связи с этим у меня вопрос возник.
Вызываем, например, так:
C++
1
func(std::shared_ptr<T>(new T(2, 3)).get())
При этом внутри функции, разумеется, объект не удаляем.
Эксперимент на единственном компиляторе показывает, что объект удаляется после использования внутри функции. И тут обнаружился пробел в моих знаниях: есть ли гарантия такого поведения со стороны стандарта?

P.S. Вряд ли я буду использовать такую конструкцию Просто интересно стало.
1
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
02.08.2012, 00:24 10

Не по теме:

[Заблуждение] Ну, не знаю, как насчёт стандарта (лень), но это ожидаемое поведение. При входе в функцию в стеке создаётся shared_ptr, который создаёт T и запоминает его. При выходе из функции стек очищается, у shared_ptr вызывается деструктор, счётчик ссылок уменьшается до нуля (если из функции shared_ptr не выносили), созданный T нормально удаляется shared_ptr, так как счётчик ссылок на нуле.



Тьфу, не заметил get(). Ммм... Интересно, считается ли подобный вызов типа-рекурсивным. То есть удаляется ли временный shared_ptr после вызова функции или после вычисления аргумента. Но это уже точно в стандарт надо идти.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
02.08.2012, 00:29 11
У меня не было бы сомнений, если бы в функцию передавался бы сам умный указатель. Сомнения возникли из-за того, что в функцию передаётся результат вызова функции .get(), после чего сам умный указатель уже как бы и ни при чём. Ладно, потом постараюсь покопаться в стандарте.

Добавлено через 58 секунд
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Тьфу, не заметил get(). Ммм...
Ага. Вот.
0
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
02.08.2012, 00:38 12
Лучший ответ Сообщение было отмечено как решение

Решение

Посмотрел. [class.temporary]/3:
When an implementation introduces a temporary object of a class that has a non-trivial constructor (12.1, 12.8), it shall ensure that a constructor is called for the temporary object. Similarly, the destructor shall be called for a temporary with a non-trivial destructor (12.4). Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception.
То есть в данном случае временный shared_ptr обязан удаляться после того, как заканчивается вычисления выражения, содержащего вызов функции. То есть гарантированно после того, как мы вернёмся из функции; не важно, нормальным образом или через исключение. Например, в случае
C++
1
foo(bar(std::shared_ptr<T>(new T(4, 2)).get()));
временный shared_ptr должен удаляться (соответственно, с деструктором, счётчиком ссылок и удалением хранимого T) или после возвращения значения функцией foo, или после того, как мы вылетим из неё из-за исключения.

Так что да, имеет право на жизнь. Ну, фактически, это тот самый точечный GC.
3
02.08.2012, 00:38
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.08.2012, 00:38
Помогаю со студенческими работами здесь

Ссылки на временные объекты
Здравствуйте! В процессе экспериментов с С++ появились некоторые непонятки. Рассмотрим код: ...

Временные объекты встроенного типа
Привет! пытаюсь углубляться в C++, решил почитать книгу Саттера, на первом примере, остановился и...

Где хранятся временные объекты?
В какой области памяти хранятся временные объекты если они не константные и на них ничего не...

Анонимные объекты(?), область определения
Не буду говорить лишнего, сразу вопрос: Что мы делаем записью &quot;new ActionListener()&quot;, &quot;new...

Скажите, пожалуйста, что такое каталог tmp и что такое временные временные файлы?
Только начал изучать файлы и работу над ними и столкнулся вот с таким вопросом. Скажите...

Анонимные сообщения
Как реализовать скрипт ответа, через цыкл вытаскиваю ответы, проверяет имеет ли сообщение...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru