0 / 0 / 1
Регистрация: 15.04.2013
Сообщений: 184
1

Временные объекты встроенного типа

21.01.2015, 18:45. Показов 2900. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Привет! пытаюсь углубляться в C++, решил почитать книгу Саттера, на первом примере, остановился и запутался, там в конце, в виде советов, которыми должен пользоваться человек при использовании итераторов, написано следующее
"4 . Некорректные встроенные операции. Не пытается ли код модифицировать временный объект встроенного типа( как в случае --e.end()"
я не смог понять смысл этого, написал такой пример, и он вроде работает
вот,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
 
int _tmain(int argc, _TCHAR* argv[])
{
    vector<string> e;
    copy(istream_iterator<string>(cin),
        istream_iterator<string>(), back_inserter(e));
    std::cout << std::endl << "Result : " << std::endl;
    copy(e.begin(), e.end(), ostream_iterator<string>(cout, "\n"));
    e.insert(--e.end(), "Tets");  
    copy(e.begin(), e.end(), ostream_iterator<string>(cout, "\n"));
    return 0;
}
так что же это за "временные объекты встроенного типа" ?
Всем спасибо за внимание и помощь!!!
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.01.2015, 18:45
Ответы с готовыми решениями:

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

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

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

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

16
18822 / 9826 / 2401
Регистрация: 30.01.2014
Сообщений: 17,260
21.01.2015, 19:22 2
Цитата Сообщение от Misha_prog Посмотреть сообщение
так что же это за "временные объекты встроенного типа" ?
Ответ на этот вопрос есть в книге чуть выше по тексту:
The reason is simple, if a little obscure: On popular implementations of the standard library,
vector<Date>::iterator is often simply a Date*, and the C++ language doesn't allow you to modify
temporaries of builtin type. For example, the following plain-jane code is also illegal:
C++
1
2
Date* f(); // function that returns a Date*
p = --f(); // error, but could be "f() - 1"
Добавлено через 2 минуты
Цитата Сообщение от Misha_prog Посмотреть сообщение
я не смог понять смысл этого, написал такой пример, и он вроде работает
В данном случае работает, потому что итератор - это не объект встроенного типа в реализации стандартной библиотеки твоего компилятора. Саттер говорит о том, что нет гарантий, что это всегда будет так.
1
0 / 0 / 1
Регистрация: 15.04.2013
Сообщений: 184
21.01.2015, 22:51  [ТС] 3
Спасибо Большое, за ответ, теперь я понял почему у меня код работает !!! Просто меня сама формулировка
Временные переменные встроенного типа смутила, я не могу смысл понять, почему они так называются. теперь я вот так понимаю, почему так делать нельзя, Схожая ситуация получается и при возврате константной ссылки, как здесь :
C++
1
2
3
4
5
6
7
8
string const & getString(string & t) {
    t += "+";
    return t;
}
int _tmain(int argc, _TCHAR* argv[])
{
    string t = "name";
    getString(t) += "tes"; // здесь ошибка
Правильно ли я понимаю? или нет?

Спасибо!!!
А вот почему они так называются я понять не могу
Временные - ?
Встроенного - ?(есть предположение,что это потому что итераторы преобразуется к указателю ?)

Спасибо ещё раз за внимание и помощь!!!
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
21.01.2015, 23:07 4
ознакомтесь еще с 19 правилом из вот этой книги:
http://rsdn.ru/res/book/cpp/most_effective_cpp.xml
Наиболее эффективное использование C++. 35 новых рекомендаций по улучшению ваших программ и проектов
Автор: Скотт Мейерс

как раз по теме временных объектов. может станет более понятно.
из нее я вот такой вывод сделал:
изменения временного объекта встроенного типа никто не заметит. результат изменения никуда не присовить.
поэтому нефиг это делать.

встроенные - это всякие там инты, чары, указатели на любые объекты.
не встроенные, они же пользовательские - это классы и прочее.
с изменением пользовательских временных объектов - ситуация такая:
можно считать изменением вызов неконстантного метода. он может иметь побочный эффект
и изменения распространятся за пределы этого объекта. поэтому запрещать вроде не стоит.
изменить за счет изменения какого-то публичного члена. тут вроде как изменения никто не заметит.
разрешено это или нет - хз. но делать так наверно не стоит, т.к. это изменение никто не заметит.
1
18822 / 9826 / 2401
Регистрация: 30.01.2014
Сообщений: 17,260
21.01.2015, 23:08 5
Лучший ответ Сообщение было отмечено Misha_prog как решение

Решение

Цитата Сообщение от Misha_prog Посмотреть сообщение
Временные - ?
Встроенного - ?(есть предположение,что это потому что итераторы преобразуется к указателю ?)
Ну я же привел цитату. В русском издании разве про это не написано? Я просто не имею возможности посмотреть, у меня эта книжка на английском.
Саттер пишет, что итератор в векторе может быть обычным указателем, а не каким-то классом, например. А указатель - это встроенный тип.
Временная переменная - это то, что возвратила нам функция end(). Правильно это назвается r-value.
Итого, если итератор в векторе реализован через обычный указатель и мы начинаем менять rvalue (посредством операции ++), которое возвратила нам end(), то получим ошибку компиляции. Если же итератор - это какой-то класс, то ошибки не будет, код скомпилируется. Поэтому он и говорит, что так делать не нужно. Потому что писать код, который зависит от фазы луны реализации стандартной библиотеки в компиляторе - плохо.
1
0 / 0 / 1
Регистрация: 15.04.2013
Сообщений: 184
22.01.2015, 17:33  [ТС] 6
Спасибо Огромное за помощь!!!Теперь понял!
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
22.01.2015, 18:31 7
Цитата Сообщение от DrOffset Посмотреть сообщение
Итого, если итератор в векторе реализован через обычный указатель и мы начинаем менять rvalue (посредством операции ++), которое возвратила нам end(), то получим ошибку компиляции.
Я одного так и не понял: а почему нельзя то? Смысли, почему нельзя менять состояние временного объекта фундаментального типа?

C++
1
2
3
4
5
6
7
8
#include <iostream>
 
int foo() { return 10; }
 
int main()
{
    std::cout << (++foo())+1 <<'\n';
}
Время жизни временного объекта - до конца всего выражения.

Получается, что принципиальной разницы между:

C++
1
std::cout << (++foo())+1 <<'\n';
и

C++
1
std::cout << (foo()+1)+1 <<'\n';
Нет.

(создание ещё одного временного объекта во втором примере опускаем).

Ну и в чем проблема то?
С чем связанно ограничение?
0
18822 / 9826 / 2401
Регистрация: 30.01.2014
Сообщений: 17,260
23.01.2015, 00:08 8
Цитата Сообщение от hoggy Посмотреть сообщение
С чем связанно ограничение?
Рискну предположить, что причины те же, что запрещают биндить временные объекты к неконстантной ссылке.
1
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
23.01.2015, 00:12 9
Цитата Сообщение от DrOffset Посмотреть сообщение
Рискну предположить, что причины те же, что запрещают биндить временные объекты к неконстантной ссылке.
Нет такого запрета. Известно, что неконстантная ссылка не продлевает жизнь временного объекта.
Это означает, что ссылка будет недействительной.

Тем не менее это даже работает. Вижал студия кричит ворнингами, но по удачному стечению обстоятельств трупы ещё даже протухнуть не успевают.

В том, что касается данной ситуации: временный объект живой. Он не умрет, пока не завершится все выражение.
В этом смысле проблем нет.
1
18822 / 9826 / 2401
Регистрация: 30.01.2014
Сообщений: 17,260
23.01.2015, 01:08 10
Цитата Сообщение от hoggy Посмотреть сообщение
Поскольку, если бы были подобного рода технические ограничения, то это распространялось бы на любые временные объекты, включая объекты пользовательских типов.
Разве ограничения на такую привязку технические? Они чисто идеологические. Что собственно подтверждает нестандартное расширение студии, которое позволяет делать такую привязку. Стандарт, кстати, не запрещает продлевать время жизни по любой ссылке, как константной, так и неконстантной, но запрещает делать привязку к неконстантной.
Впрочем, если тебе хочется поспорить, то это мимо. Я не имею ни малейшего желания это делать и лишь высказал свое мнение. Если тебя оно не устраивает, предлагаю подождать других.

Добавлено через 47 минут
hoggy, во дела. Отвечал на один пост, а теперь вижу совсем другой. Мистика
Ладно, наверное надо объяснить что я имел в виду.
Рассмотрим вот такой код:
C++
1
2
3
4
5
6
7
8
struct A
{
    A & operator++();
};
 
A foo();
 
++foo();
Возвращаемый объект неконстантный, код работает. Т.к. объект неконстантный, то this внутри метода тоже указывает на неконстанту. Т.е. все хорошо и все работает.
Теперь заменим A на int. Что изменилось? int - это не класс. И, я думаю, никто не будет спорить, что у int не может быть методов. Значит ++ по отношению к int - внешняя функция. И вот тут как раз вступает в силу упомянутый мной момент с const reference. Если operator++ по отношению к int внешняя функция, то ее прототип (псевдокод) будет выглядеть так:
C++
1
int & operator++(int & a);
И вот теперь мы видим, почему это не работает. Нельзя биндить rvalue к неконстантной ссылке.
Проделаем тоже самое с классом. Сделаем operator++, но уже внешней функцией
C++
1
2
3
A & operator++(A & a);
 
++foo();
и убедимся, что код тоже перестал работать. Поведение сравнялось.
Я думаю все теперь на своих местах.
1
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
23.01.2015, 01:45 11
Цитата Сообщение от DrOffset Посмотреть сообщение
И вот теперь мы видим, почему это не работает. Нельзя биндить rvalue к неконстантной ссылке.
Не вижу проблемы.
Почему нельзя то???

Цитата Сообщение от DrOffset Посмотреть сообщение
но запрещает делать привязку к неконстантной.
С чем это связанно?

Понятно, что если бы он это узаконил - можно было бы прострелить себе ногу, а компилятор бы даже ворнингом не пискнул.

C++
1
2
some& ref = foo();
ref.work(); //uppssss
Но штука в том, что и сейчас с таким же успехом можно прострелить себе ногу.
Это ограничение просто не спасет:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
struct A
{
    A& operator++() { return *this; }
};
 
A foo() { return A(); }
 
//A& operator++(A& a){ return a; }
 
int main()
{
    std::cout << "Hello, world!\n";
    
    A& ref = ++foo(); //uppsss
}
Это принципиально ничем не отличается от:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
struct A
{
    //A& operator++() { return *this; }
};
 
A foo() { return A(); }
 
A& operator++(A& a){ return a; }
 
int main()
{
    std::cout << "Hello, world!\n";
    
    A& ref = ++foo(); //error: no match for ‘operator++’ (operand type is ‘A’)
}
А кроме того, стандарт никогда не запрещал программистам стрелять себе в ногу.

Что бы там ни было, но причина явно не идеологическая.
1
18822 / 9826 / 2401
Регистрация: 30.01.2014
Сообщений: 17,260
23.01.2015, 02:00 12
Цитата Сообщение от hoggy Посмотреть сообщение
Не вижу проблемы.
Как мне кажется, на изначальный твой вопрос, о том чем int "хуже" чем класс, я ответил. Дальше уже нужно рассматривать почему таки нельзя биндить rvalue к неконстантной ссылке. Но это уже другой вопрос.

Добавлено через 12 минут
Цитата Сообщение от hoggy Посмотреть сообщение
Это ограничение просто не спасет
Оно и не спасает. Все правильно.
Я повторюсь, не хочу спорить по этому вопросу. Но мое мнение такое, что это заплатка именно идеологическая. Попытка хоть чуть-чуть внести контроль на уровне синтаксиса. Дело в том, что литерал - тоже rvalue, видимо поэтому решено было запретить биндинги к неконстантной ссылке для всех rvalue, чтобы не плодить лишних исключений из правил.
C++
1
2
int const & a = 2; // вполне логично
int & b = 2; //абсурд
2
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
23.01.2015, 09:52 13
Цитата Сообщение от DrOffset Посмотреть сообщение
Дело в том, что литерал - тоже rvalue, видимо поэтому решено было запретить биндинги к неконстантной ссылке для всех rvalue, чтобы не плодить лишних исключений из правил.
Это было бы похоже на правду, если бы компилятор не умел различать константные rvalue от неконстантных.
Однако умеет. Более того: это не есть фича нового стандарта.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
struct example
{
    void baz(){ std::cout << "foo\n"; }
};
 
const example foo(){ return example(); }
 
int main()
{
    std::cout << "Hello, world!\n";
    
    foo().baz(); //error: passing ‘const example’ as ‘this’ argument 
           //of ‘void example::baz()’ discards qualifiers 
}

На самом деле это просто похоже на ещё один откровенный ляп в дизайне языка, на который и комитет, и сообщество тупо положили с прибором.
1
Эксперт по математике/физикеЭксперт С++
2044 / 1363 / 393
Регистрация: 16.05.2013
Сообщений: 3,498
Записей в блоге: 6
23.01.2015, 12:02 14
 Комментарий модератора 
hoggy, Xelort,
Прошу вас обратить внимание на название раздела в котором вы находитесь. Здесь люди деляться опытом и знаниями. Что-то не знать здесь позволительно, а вот провоцировать или грубить ни как не разрешается.
Продолжите в том же духе получите по попе. Оба.


Добавлено через 23 минуты
 Комментарий модератора 
hoggy, Xelort, последнее предупреждение.
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
23.01.2015, 23:16 15
эмммм, у последнего примера ошибка из-за вызова неконстантного метода у константного объекта.
вроде это не совсем по теме временных объектов.

немного пользы для тех, кто не знаком с такой штукой:
тут уже было сказано что неконстантная ссылка не продлевает жизнь объекту.
а вот константная таки продлевает:

C++
1
2
3
4
5
6
7
std::string& foo()
{
   return "ddd";
}
 
const std::string& str = foo();
bool empty = str.empty(); // это корректно, несмотря на то, что str - ссылка
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
23.01.2015, 23:54 16
Цитата Сообщение от DU2 Посмотреть сообщение
а вот константная таки продлевает:
У вас тут UB

C++
1
2
3
4
5
6
7
8
9
10
std::string& foo()   //<--- возвращает ссылку, которая не продлевает жизнь
{
   return "ddd"; //<--- создание временного объекта
}
 
const std::string& str = foo(); //<--- продлевает жизнь... не констатной ссылки
   //а вот временный объект к этому моменту уже мертв
 
bool empty = str.empty(); // это не корректно, потому что к этому моменту временный объект
   // уже протухнуть может
Продлевать жизнь нужно самим объектам, а не ссылкам:

C++
1
2
3
4
5
6
7
8
std::string foo()   //<--- возвращает объект
{
   return "ddd"; //<--- создание временного объекта
}
 
const std::string& str = foo(); //<--- продлевает жизнь временного объекта
 
bool empty = str.empty(); // <--- можно
1
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
24.01.2015, 00:10 17
черт. опечатка вышла. ссылка при возврате из функции не предполагалась
0
24.01.2015, 00:10
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.01.2015, 00:10
Помогаю со студенческими работами здесь

Деструктор для встроенного типа
Вечер добрый. Какой смысл у деструктора для встроенных типов? Такое вообще должно работать или...

Как создать шаблон для пользовательского и встроенного типа?
Есть перегруженные операторы класса: void String::operator=(const char *a){ //Перегрпуженный...

Как присвоить переменной своего класса переменную встроенного типа
Подскажите пожалуйста?!Как присвоить переменной своего класса переменную встроенного класса? ...

"Анонимные" (временные) объекты?
Пусть имеется класс T: class T { public: int a; int b; T(int _a, int _b) : a(_a), b(_b) {}...


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

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

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