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

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

Войти
Регистрация
Восстановить пароль
 
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
#1

Время приобретения объектом константности - C++

20.07.2014, 17:31. Просмотров 517. Ответов 14
Метки нет (Все метки)

Всем привет
Есть такая ситуация:
C++
1
2
3
4
5
6
7
8
// Функция:
void someFunc(const std::vector<MyObj> objects);
 
 
std::vector<MyObj> makeObjectsVector() { /* --- */ }
 
// Вызываю её так:
someFunc( makeObjectsVector() ); // сработает ли move-конструктор, ведь someFunc принимает const?
Добавлено через 4 минуты
Код собрался, даже не пищал, но если move-конструктор оставляет принятый как параметр объект in valid but unspecified state, то значит он должен как-то изменить состояние его, а сл-но константность параметра функции someFunc приобретается уже после перемещения?

К чему все это: в функции этот перемещаемый объект никак не изменяется, а только читается, а у меня привычка объявлять такие вещи как const.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.07.2014, 17:31
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Время приобретения объектом константности (C++):

Обход константности переменной - C++
в классе есть метод с разными параметрами: int Find(const WCHAR* Val, size_t Beg = 0, size_t Len = 0){ ... }; template...

Почему компилятор требует константности для заданного метода? - C++
Приветствую всех! Имеется класс Fraction с перегруженными операциями сложения, вычитания, умножения и деления. Перегруженные операции...

Работа с объектом. - C++
Вот код: struct time { int hours; int mituts; } class pet {

Синхронная работа с объектом - C++
Здравствуйте. Возможно ли работать с объектом одновременно в нескольких функциях/процессах, имея его адрес в динамической памяти? Если да,...

Возвращение объектом значения - C++
Привет всем. Работал я тут на днях с классом fstream и увидал классную штуку, скажем: .... fstream file; ...

Проблема с объектом string - C++
Всем привет! Таким образом передаю текст объекту string: string str ; sscanf( &quot;cyberforum.ru&quot;, &quot;%s&quot; , str.data() ); cout &lt;&lt; &quot;string...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
-=ЮрА=-
Заблокирован
Автор FAQ
20.07.2014, 17:53 #2
Цитата Сообщение от gromo Посмотреть сообщение
void someFunc(const std::vector<MyObj> &objects);
- !!!!
0
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
20.07.2014, 17:55  [ТС] #3
-=ЮрА=-, вы наверное имеете ввиду NamedReturnValueOptimization? Может это и сработает, но я хочу именно использовать перемещение, потому что оно гарантированно сэкономит ресурсы там, где NRVO может и не получиться.
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.07.2014, 18:02 #4
gromo, в твоём случае создаётся копия объекта
См ниже что вызовется при вызове SomeFunc1
C++
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
32
33
34
#include <iostream>
using namespace std;
class CSomeClass
{
    public:
    CSomeClass();
    CSomeClass(const CSomeClass &pCopy);
    friend void SomeFunc1(const CSomeClass  obj);
    friend void SomeFunc2(const CSomeClass &obj);
};
 
CSomeClass::CSomeClass(){
    cout<<"DEFAULT CONSTRUCTOR"<<endl;
}
 
CSomeClass::CSomeClass(const CSomeClass &pCopy){
    cout<<"COPY CONSTRUCTOR"<<endl;
}
 
void SomeFunc1(const CSomeClass  obj){
    cout<<"SomeFunc1"<<endl;
}
 
void SomeFunc2(const CSomeClass &obj){
    cout<<"SomeFunc2"<<endl;
}
 
int main()
{
    CSomeClass pObj;
    SomeFunc1(pObj);
    SomeFunc2(pObj);
    return 0;
}
DEFAULT CONSTRUCTOR
COPY CONSTRUCTOR
SomeFunc1
SomeFunc2
http://codepad.org/sPPIfdry

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от gromo Посмотреть сообщение
но я хочу именно использовать перемещение,
- тогда сделай нормальный Swap

1
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
20.07.2014, 18:36  [ТС] #5
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
См ниже что вызовется при вызове SomeFunc1
Так то да, вызовется копирующий конструктор. Однако в моем примере кода на вход someFunc подается объект из некого фабричного help-метода ( на практике это может быть std::make_pair, std::make_tuple...).
Если расширить ваш класс так
C++
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
using namespace std;
class CSomeClass
{
    public:
    CSomeClass();
    CSomeClass(const CSomeClass &pCopy);
    friend void SomeFunc1(const CSomeClass  obj);
    friend void SomeFunc2(const CSomeClass &obj);
 
    CSomeClass(CSomeClass &&other) : m_variable(other.m_variable)
    {
        other.m_variable = 0;
        std::cout << "Move Constructor" << std::endl;
    }
    int m_variable;
};
 
CSomeClass::CSomeClass(){
    cout<<"DEFAULT CONSTRUCTOR"<<endl;
}
 
CSomeClass::CSomeClass(const CSomeClass &pCopy){
    cout<<"COPY CONSTRUCTOR"<<endl;
}
 
void SomeFunc1(const CSomeClass  obj){
    cout<<"SomeFunc1"<<endl;
}
 
void SomeFunc2(const CSomeClass &obj){
    cout<<"SomeFunc2"<<endl;
}
 
CSomeClass someClassFactory()
{
    CSomeClass csc;
    return csc;
//    return std::move(csc);
}
 
int main()
{
    CSomeClass pObj;
    SomeFunc1(pObj);
    SomeFunc2(pObj);
    std::cout << "-------------------------------------"   << std::endl;
 
    SomeFunc1( someClassFactory() );
 
    return 0;
}
При вызове SomeFunc1 не вызывается копирующего конструктора, сработала NRVO.
Но если в someClassFactory() раскомментировать 2 вариант return'a то сработает move-конструктор и опять же не будет копирования. Как видно, в move-конструкторе изменяется m_variable, даже если и параметр функции someFunc1 объявлен как const. А это и есть ответ на мой вопрос, т.е. объект приобретает константность после перемещения и move constructor все-таки сработает.

К сожаления codepad.org не распознает && поэтому могу только предоставить свой вывод в gcc.
Время приобретения объектом константности
0
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
20.07.2014, 18:59  [ТС] #6
___
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.07.2014, 20:03 #7
gromo, у тебя в коде глупость
Цитата Сообщение от gromo Посмотреть сообщение
CSomeClass(CSomeClass &&other)
http://codepad.org/3OM4ziqi

Добавлено через 1 минуту

Не по теме:

Ещё раз хочешь не убивая данных отдать их новому объекту - пиши Swap хочешь КК без создания временного объекта - пережавай константную ссылку.Не хочешь слушать дело твоё.

0
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
20.07.2014, 20:09  [ТС] #8
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
у тебя в коде глупость
ну я ж написал, что этот онлайн-компилятор не кушает rvalue references, и выше прикрепил скриншот выдачи своего локального компилятора.

Добавлено через 3 минуты
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
пиши Swap хочешь КК без создания временного объекта - пережавай константную ссылку.
Зачем писать swap если он есть в STL? А с move конструктором обмен и так будет без временного объекта ( во всяком случае почти без затрат на его создание )
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.07.2014, 20:16 #9
gromo, присвоить нуль таким образом
other.m_variable = 0
контейнеру у тебя не выйдет. Работай с указателями и swap-ом, так сможешь обменять данные без перевыделений. Либо приведи нормальный код чтобы можно было толком понять что куда хочешь переместить.
0
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
20.07.2014, 20:21  [ТС] #10
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
присвоить нуль таким образом
other.m_variable = 0
контейнеру у тебя не выйдет.
это ясно, здесь переменная типа int для примерa. Контейнеры работают с аллокаторами, которые и распоряжаются перемещаемыми ресурсами. ( в зависимости от propagate_on_container_move_assignment ) На самом деле там может ничего и не присваиваться, только при попытке доступа к перемещенному контейнеру ( или любому другому объекту ) получим UB.
0
Tulosba
:)
Эксперт С++
4396 / 3239 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
20.07.2014, 20:50 #11
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
у тебя в коде глупость
Ох, снова ты не разобрался что к чему и начинаешь писать чушь.
Твой любимый codepad не поддерживает C++11. И ты, судя по всему, тоже не знаешь, что такое && в современном C++.

Добавлено через 13 минут
gromo, вот, можно посмотреть на цепочку вызовов:
http://coliru.stacked-crooked.com/a/e3e0fd28be3909cb
Основной момент в использовании ключа -fno-elide-constructors иначе срабатывает оптимизация и дело до конструктора перемещения не доходит вовсе.
1
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
20.07.2014, 21:12  [ТС] #12
Цитата Сообщение от Tulosba Посмотреть сообщение
иначе срабатывает оптимизация и дело до конструктора перемещения не доходит вовсе.
Ого, лучше наверное пускай срабатывает оптимизация - 2 вызова против 6 (!!!).
Только один момент остался неясен.
Если с -fno-elide-constructors то имеем такую цепочку ( метки #1 #2 )
C++
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
#include <vector>
#include <iostream>
 
struct V
{
    V() { std::cout << "ctor\n"; }
    ~V() { std::cout << "dtor\n"; }
    V(const V&) { std::cout << "copy ctor\n"; }
    V(V&&) { std::cout << "move ctor\n"; }
};
 
// Функция:
void someFunc(const V v) // #2 перемещение, деструктор, деструктор.
{
    std::cout << "someFunc" << std::endl;
}
 
V makeObject()
{
    return V(); // #1  конструктор, перемещение, деструктор
}
 
int main()
{
    someFunc( makeObject() );
}
Для чего второй раз вызвался деструктор в #2 ?
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.07.2014, 21:24 #13
C++
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <vector>
#include <iostream>
using namespace std;
 
class CSomeClass
{
    protected:
    vector<int> * lpData;
    public:
    CSomeClass();
    void SwapData(CSomeClass &pCopy);
    void SetItemCount(int count= 0);
    size_t GetItemCount() const;
};
 
CSomeClass::CSomeClass(){
    lpData = 0;
}
 
void CSomeClass::SwapData(CSomeClass &pCopy){
    swap(lpData, pCopy.lpData);
}
 
void CSomeClass::SetItemCount(int count)
{
    if( lpData )
        lpData->resize(count);
    else
    if( lpData = new vector<int>() )
        SetItemCount(count);
}
 
size_t CSomeClass::GetItemCount() const{
    size_t count = 0;
    if( lpData )
        count = lpData->size();
    return count;
}
 
void Notify(const CSomeClass &srs, 
const  CSomeClass &dst, const  CSomeClass &cpy, const char * msg = 0);
 
int main()
{
    CSomeClass srs;
    CSomeClass dst;
    CSomeClass cpy;
    Notify(srs, dst, cpy, "INIT : ");
    srs.SetItemCount(10);
    Notify(srs, dst, cpy, "SRS::SetItemCount(10) : ");
    dst.SwapData(srs);
    Notify(srs, dst, cpy, "DST::SwapData(SRS) : ");
    cpy.SetItemCount(5);
    Notify(srs, dst, cpy, "CPY::SetItemCount(10) : ");
    cpy.SwapData(dst);
    Notify(srs, dst, cpy, "CPY::SwapData(DST) : ");
    cin.get();
    return 0;
}
 
void Notify(const CSomeClass &srs, const CSomeClass &dst,const  CSomeClass &cpy, const char * msg)
{
    if( msg )
    cout<<msg<<endl;
    cout<<"SRS : "<<srs.GetItemCount()<<endl;
    cout<<"DST : "<<dst.GetItemCount()<<endl;
    cout<<"CPY : "<<cpy.GetItemCount()<<endl;
}
INIT :
SRS : 0
DST : 0
CPY : 0
SRS::SetItemCount(10) :
SRS : 10
DST : 0
CPY : 0
DST::SwapData(SRS) :
SRS : 0
DST : 10
CPY : 0
CPY::SetItemCount(10) :
SRS : 0
DST : 10
CPY : 5
CPY::SwapData(DST) :
SRS : 0
DST : 5
CPY : 10
http://ideone.com/cPRRfj
0
Tulosba
:)
Эксперт С++
4396 / 3239 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
20.07.2014, 21:43 #14
gromo, три конструктора, три деструктора. Всё вроде бы логично.
1
gray_fox
20.07.2014, 22:14     Время приобретения объектом константности
  #15

Не по теме:

Цитата Сообщение от gromo Посмотреть сообщение
этот онлайн-компилятор не кушает rvalue references
ideone может, если что.

0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.07.2014, 22:14
Привет! Вот еще темы с ответами:

Конструктор с параметром-объектом - C++
class a { private: ... public: a (); ... }; class b {

Работа с классом и объектом Вектор - C++
Являюсь студентом,и по долгу учебы приступил к обучению премудростям &quot;оСей с двумя плюсами&quot;. И обломался. получил задание на...

Возврат значения объектом класса - C++
Может ли экземпляр класса возвращать значение своего поля без обращения к полю напрямую например class MyClass { int val = 5;...

Задача на строки, с объектом класса string - C++
Дано осмысленное текстовое сообщение, разделенное пробелами и знаками препинания, в конце ставится точка. Поменять слова в сообщении по...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
20.07.2014, 22:14
Ответ Создать тему
Опции темы

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