Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.90
edward_jonson
158 / 158 / 25
Регистрация: 23.02.2011
Сообщений: 392
#1

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

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

Пусть имеется класс 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)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.08.2012, 19:08
Здравствуйте! Я подобрал для вас темы с ответами на вопрос "Анонимные" (временные) объекты? (C++):

В зависимости от времени года "весна", "лето", "осень", "зима" определить погоду "тепло", "жарко", "холодно", "очень холодно" - C++
В зависимости от времени года &quot;весна&quot;, &quot;лето&quot;, &quot;осень&quot;, &quot;зима&quot; определить погоду &quot;тепло&quot;, &quot;жарко&quot;, &quot;холодно&quot;, &quot;очень холодно&quot;. Я так...

Работа с памятью: можно ли в массив объектов с полем типа "Родитель", вписать объекты с полем типа "Потомок" - C++
Здравствуйте. Предположим, что у нас есть массив из структур в которых находиться класс Item и число Count. Можно ли на место Item записать...

Реализовать классы "Воин", "Пехотинец", "Винтовка", "Матрос", "Кортик" (наследование) - C++
Разработать программу с использованием наследования классов, реализующую классы: − воин; − пехотинец(винтовка); − матрос(кортик). ...

"Классы и объекты" -"операторы" - C++
Объект «множество целых чисел удвоенной длины заданной мощности». Предусмотреть возможность операции присваивания, объединения двух...

Создать абстрактный класс "Издание" и производные классы "Книга", "Статья", "Электронный ресурс" - C++
1. Создать абстрактный класс Издание с методами, позволяющими вывести на экран информацию об издании, а также определить является ли данное...

Создать класс "Вентилятор" содержащий в себе классы: "Двигатель", "Контроллер", "Пульт управления" - C++
Помогите с кодом написания задачи, не понимаю как написать классы в классе. Нужно создать класс &quot;вентилятор&quot; содержащий в себе классы:...

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

Добавлено через 18 секунд
Цитата Сообщение от edward_jonson Посмотреть сообщение
кстати ворнингами ругается компилятор
по***
1
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 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
edward_jonson
158 / 158 / 25
Регистрация: 23.02.2011
Сообщений: 392
01.08.2012, 21:28  [ТС] #6
~OhMyGodSoLong~, не совсем, нужно именно указатель передать
0
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 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
1484 / 1130 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
01.08.2012, 23:26 #8
добавлю, что случаи, когда владение объектом нужно передать функции, которая должна будет удалить его, лучше оформлять в виде соответствующих смарт-поинтеров, чтобы явно подчеркнуть факт того, что объект удалится внутри функции. иначе это нужно будет описывать в каментариях, либо лезть в код функции и смотреть, что она делает с простым указателем.
0
grizlik78
Эксперт С++
1966 / 1459 / 120
Регистрация: 29.05.2011
Сообщений: 3,019
01.08.2012, 23:49 #9
А вот в связи с этим у меня вопрос возник.
Вызываем, например, так:
C++
1
func(std::shared_ptr<T>(new T(2, 3)).get())
При этом внутри функции, разумеется, объект не удаляем.
Эксперимент на единственном компиляторе показывает, что объект удаляется после использования внутри функции. И тут обнаружился пробел в моих знаниях: есть ли гарантия такого поведения со стороны стандарта?

P.S. Вряд ли я буду использовать такую конструкцию Просто интересно стало.
1
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 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
grizlik78
Эксперт С++
1966 / 1459 / 120
Регистрация: 29.05.2011
Сообщений: 3,019
02.08.2012, 00:29 #11
У меня не было бы сомнений, если бы в функцию передавался бы сам умный указатель. Сомнения возникли из-за того, что в функцию передаётся результат вызова функции .get(), после чего сам умный указатель уже как бы и ни при чём. Ладно, потом постараюсь покопаться в стандарте.

Добавлено через 58 секунд
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Тьфу, не заметил get(). Ммм...
Ага. Вот.
0
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 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
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.08.2012, 00:38
Привет! Вот еще темы с ответами:

Создать класс "Книга" с полями "название книги", "количество страниц", "год издания" - C++
Создать класс Книга поля: название книги,количество страниц,год издания методы: вычислить сколько лет книге и количество дней прошедших...

Определить тип данных "Запись", имеющий поля "Фамилия", "Пол", "Зарплата" - C++
определить тип данных запись имеющий поля фамилия пол зарплата. определить массив из 10 записей. в программе ввести в массив данные и...

Структура «Преподаватель» с полями "ФИО", "стаж", "категория", "нагрузка" - C++
Функция - расчёт зарплаты по нагрузке и оплате часа для определенной категории. Категория Оплата часа Вторая 150 Первая 200 ...

Реализовать структуру "Анкета" с полями "Фамилия", "Пол" и "Адрес" - C++
Здравствуйте. Проходим тему Структуры, не могу понять, как определить количество, само задание: #include &lt;iostream&gt; #include...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru