Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.90
edward_jonson
 Аватар для edward_jonson
157 / 157 / 25
Регистрация: 23.02.2011
Сообщений: 388
01.08.2012, 19:08     "Анонимные" (временные) объекты? #1
Пусть имеется класс 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) );
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.08.2012, 19:08     "Анонимные" (временные) объекты?
Посмотрите здесь:

C++ Необработанное исключение в "0x54a2d2e9 (msvcr100d.dll)" в "3.exe": 0xC0000005: Нарушение прав доступа при записи "0xcccccccc".
Необработанное исключение в "0x1027c9c7 (msvcr100d.dll)" в "gh.exe": 0xC0000005: Нарушение прав доступа при чтении "0xfeeefeee". C++
Вывести текст файла, заменив цифры от 0 до 9 на слова "ноль", "один"."девять", начиная каждое предложение с новой строки C++
Необработанное исключение в "0x0fc1d484 (msvcr100d.dll)" в "1.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00aee0af" C++
C++ "Классы и объекты" -"операторы"
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Vourhey
Почетный модератор
6468 / 2243 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
01.08.2012, 19:13     "Анонимные" (временные) объекты? #2
edward_jonson, убери new в вызове, будет тебе и локальный, и анонимный.
edward_jonson
 Аватар для edward_jonson
157 / 157 / 25
Регистрация: 23.02.2011
Сообщений: 388
01.08.2012, 19:20  [ТС]     "Анонимные" (временные) объекты? #3
Vourhey, вместо new - &, как в последней строке моего поста? на это кстати ворнингами ругается компилятор
Vourhey
Почетный модератор
6468 / 2243 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
01.08.2012, 19:23     "Анонимные" (временные) объекты? #4
Цитата Сообщение от edward_jonson Посмотреть сообщение
вместо new - &, как в последней строке моего поста?
Ну, так как, у тебя функция принимает указатель, то, само собой, амперсанд нужен для взятия адреса. В скобки это все дело, в идеале.

Добавлено через 18 секунд
Цитата Сообщение от edward_jonson Посмотреть сообщение
кстати ворнингами ругается компилятор
по***
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 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;
}
Так что ли?
edward_jonson
 Аватар для edward_jonson
157 / 157 / 25
Регистрация: 23.02.2011
Сообщений: 388
01.08.2012, 21:28  [ТС]     "Анонимные" (временные) объекты? #6
~OhMyGodSoLong~, не совсем, нужно именно указатель передать
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 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 получает на него указатель, а не копию; данные объекта можно менять; объект автомагически удалится из стека.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
01.08.2012, 23:26     "Анонимные" (временные) объекты? #8
добавлю, что случаи, когда владение объектом нужно передать функции, которая должна будет удалить его, лучше оформлять в виде соответствующих смарт-поинтеров, чтобы явно подчеркнуть факт того, что объект удалится внутри функции. иначе это нужно будет описывать в каментариях, либо лезть в код функции и смотреть, что она делает с простым указателем.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
01.08.2012, 23:49     "Анонимные" (временные) объекты? #9
А вот в связи с этим у меня вопрос возник.
Вызываем, например, так:
C++
1
func(std::shared_ptr<T>(new T(2, 3)).get())
При этом внутри функции, разумеется, объект не удаляем.
Эксперимент на единственном компиляторе показывает, что объект удаляется после использования внутри функции. И тут обнаружился пробел в моих знаниях: есть ли гарантия такого поведения со стороны стандарта?

P.S. Вряд ли я буду использовать такую конструкцию Просто интересно стало.
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 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 после вызова функции или после вычисления аргумента. Но это уже точно в стандарт надо идти.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
02.08.2012, 00:29     "Анонимные" (временные) объекты? #11
У меня не было бы сомнений, если бы в функцию передавался бы сам умный указатель. Сомнения возникли из-за того, что в функцию передаётся результат вызова функции .get(), после чего сам умный указатель уже как бы и ни при чём. Ладно, потом постараюсь покопаться в стандарте.

Добавлено через 58 секунд
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Тьфу, не заметил get(). Ммм...
Ага. Вот.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.08.2012, 00:38     "Анонимные" (временные) объекты?
Еще ссылки по теме:

Что такое "Структурированные типы данных. Объекты" C++
Как реализовать указатель "n" размерности на разные объекты? C++
C++ "Морской бой": массив указателей на объекты vs контейнер stl. Что лучше?

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

Или воспользуйтесь поиском по форуму:
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 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.
Yandex
Объявления
02.08.2012, 00:38     "Анонимные" (временные) объекты?
Ответ Создать тему
Опции темы

Текущее время: 11:27. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru