Russian Qt Forum

Программирование => С/C++ => Тема начата: Igors от Декабрь 04, 2016, 09:21



Название: const char *&
Отправлено: Igors от Декабрь 04, 2016, 09:21
Добрый день

Код
C++ (Qt)
void Test( const char *& src )
{
}
 
int main()
{
char * test = new char[128];
// const char * test = new char[128]; // Ok
Test(test);
return 0;
}
Почему это не компилится  ???

Спасибо


Название: Re: const char *&
Отправлено: Old от Декабрь 04, 2016, 09:43
Потому что так const char *& src вы описываете ссылку на константный указатель на char.
А вам надо char * const & src, т.е. константную ссылку на указатель на char.


Название: Re: const char *&
Отправлено: Racheengel от Декабрь 05, 2016, 01:44
а const char & * src ?


Название: Re: const char *&
Отправлено: Old от Декабрь 05, 2016, 07:00
а const char & * src ?
Не бывает указателей на ссылку.


Название: Re: const char *&
Отправлено: vbv от Декабрь 05, 2016, 09:06
>Не бывает указателей на ссылку.
Ссылка есть указатель.
Не бывает указателей на указатель.... Дожились.
Просто выглядит по другому.


Название: Re: const char *&
Отправлено: Old от Декабрь 05, 2016, 09:22
>Не бывает указателей на ссылку.
Ссылка есть указатель.
Не бывает указателей на указатель.... Дожились.
Просто выглядит по другому.
Дожили. А это что за тип?
char **val;

А теперь попробуйте указатель на ссылку скомпилировать. А лучше книгу какую нибудь по С++ почитать. :)


Название: Re: const char *&
Отправлено: Igors от Декабрь 05, 2016, 11:09
а const char & * src ?
А чего это я должен гадать?
Код
C++ (Qt)
void Test1( const char * src )
{
 ++src; // ok
 src[0] = 0; // error
}
Ф-ция принимает указатель на константу, сам указатель менять можно, данные по нему - нет. Я этого и хотел, но еще и чтобы сам указатель менялся когда ф-ция отдала упр-е. Напр прочитал слово из строки и продвинул указатель на следующее слово. Поэтому  
Код
C++ (Qt)
void Test1( const char *& src )
{
 ++src; // ok
 src[0] = 0; // error
}
Но почему вызывающий не может привести НЕконстантный указатель к константному - хз. Наверное просто "это другой тип", а ссылка должна быть "точно такого типа". Напр
Код
C++ (Qt)
typedef char * Ptr;
typedef const char * CPtr;
 
void Test( CPtr & src );
 
Ptr src;
Test(src); // error
Выходит нельзя сделать ссылку на CPtr из Ptr. Или я фантазирую?


Название: Re: const char *&
Отправлено: Авварон от Декабрь 05, 2016, 11:29
Возможно, тут работает правило "1 встроенное преобразование, 1 пользовательское преобразование".
Тут встроенных преобразования 2:
1) char * -> const char *
2) const char * -> const char *&

Не уверен, правда, что это правило распространяется на ссылки.


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 05, 2016, 11:50
Ссылка есть указатель.
Ссылка не есть указатель. Ссылка хранит адрес объекта. Автоматически разименовывается при использовании.


Название: Re: const char *&
Отправлено: ViTech от Декабрь 05, 2016, 12:49
>Не бывает указателей на ссылку.
Ссылка есть указатель.
Не бывает указателей на указатель.... Дожились.
Просто выглядит по другому.

What is a reference? (https://isocpp.org/wiki/faq/references#overview-refs)


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 05, 2016, 13:03
Судя по ошибкам компилятора, полагаю, что в результате неявного преобразования char * в const char * мы получаем rvalue, от которого по стандарту нельзя брать неконстантную ссылку.


Название: Re: const char *&
Отправлено: Igors от Декабрь 05, 2016, 13:22
What is a reference? (https://isocpp.org/wiki/faq/references#overview-refs)
Отак от - тыц ссылочкой, и усе :) И что же там пишут?

Цитировать
Important note: Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object. It is not a pointer to the object, nor a copy of the object. It is the object.
А почему собсно? Изменилась "семантика" (я и такое слово знаю :)), но "физически" все тот же махровый указатель. И знать это весьма полезно, напр
Код
C++ (Qt)
Object * obj = new Object;
Object & ref = *obj;
..
delete obj;   // ref is not longer valid
 
Если это "It is the object" то какого ж <template> он стал invalid? Так что я бы не спешил тупенько повторять "что написали умные люди" - может они не так уж умны?  :) 


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 05, 2016, 13:49
Переменная = адрес объекта
Ссылка  = адрес объекта
Указатель =  адрес памяти, в которой хранится адрес объекта


Название: Re: const char *&
Отправлено: ViTech от Декабрь 05, 2016, 13:57
А почему собсно? Изменилась "семантика" (я и такое слово знаю :)), но "физически" все тот же махровый указатель. И знать это весьма полезно, ...

Разработчики стандарта языка и компиляторов отдельно подчёркивают, что ссылка - это не указатель, и не важно, как на текущий момент это внутри реализовано. Вы же свою линию гнёте :).

Код
C++ (Qt)
Object * obj = new Object;
Object & ref = *obj;
..
delete obj;   // ref is not longer valid
 
Если это "It is the object" то какого ж <template> он стал invalid?

Что здесь странного? Вы создали объект, через разыменование указателя получили доступ к нему и теперь можете обращаться к этому объекту через ссылку/псевдоним. Потом объект удалили, следовательно все его псевдонимы(ссылки на него) стали невалидными.

Так что я бы не спешил тупенько повторять "что написали умные люди" - может они не так уж умны?  :) 

Тогда можете жить в своём мире, отличном от мира "умных людей" :).


Название: Re: const char *&
Отправлено: ViTech от Декабрь 05, 2016, 14:02
Переменная = адрес объекта
Ссылка  = адрес объекта
Указатель =  адрес памяти, в которой хранится адрес объекта

Ссылка - это псевдоним объекта. Как это компилятором на текущий момент реализовано - совершенно не важно и может со временем изменяться. В каких-нибудь оптимизациях это может и не через указатель делаться. Поэтому не нужно думать о ссылке как об адресе в памяти или указателе. Это псевдоним объекта, сам объект.


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 05, 2016, 14:04
Код
C++ (Qt)
Object * obj = new Object;
Object & ref = *obj;
..
delete obj;   // ref is not longer valid
 
Если это "It is the object" то какого ж <template> он стал invalid?  


Следуя вашей логике можно сделать и
Код
C++ (Qt)
Object obj;
memset(&obj, 0, 100500);
А потом возмущаться:
Цитировать
может они не так уж умны?  :)


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 05, 2016, 14:45
не нужно думать о ссылке как об адресе в памяти или указателе.
Согласен.
Покопался в стандарте
Цитировать
8.3.2 References
...
4 It is unspecified whether or not a reference requires storage


Название: Re: const char *&
Отправлено: Авварон от Декабрь 05, 2016, 14:52
В 17х плюсах возможно можно будет перегружать оператор. и делать свои ссылки. Как организовать сторадж - это вопрос 10й


Название: Re: const char *&
Отправлено: Igors от Декабрь 05, 2016, 14:57
Указатель =  адрес памяти, в которой хранится адрес объекта
Это уже "указатель на указатель" (**)

Как это компилятором на текущий момент реализовано - совершенно не важно и может со временем изменяться. В каких-нибудь оптимизациях это может и не через указатель делаться.
Вы правда в это верите?  :)

Поэтому не нужно думать ..
Не нужно повторять чужое не осмыслив его. Не нужно наивно полагать что здесь кто-либо не читал хотя бы с десяток ссылок типа той что Вы привели. Ваши пояснения хороши для нерадивых студентов, а по жизни многие (включая меня) предпочитают думать о ссылке как о "замаскированном указателе" - и в этом есть резон. Для "самого объекта" время жизни всегда однозначно определено, для ссылки неизвестно.

Следуя вашей логике можно сделать и
Код
C++ (Qt)
Object obj;
memset(&obj, 0, 100500);
Это не следует моей логике, Вы портите содержимое объекта, но сам объект существует, напр  по-прежнему можно обращаться к его членам, пусть там и нули.  

Согласен.
Покопался в стандарте
Цитировать
8.3.2 References
...
4 It is unspecified whether or not a reference requires storage
Это значит что "замаскированный указатель" может храниться и на регистрах

Однако ж мы отвлеклись от темы. Как всегда, все проблемы легко решаются если убрать const, но это все-таки не очень хорошо, в ф-ции Test все к месту. По-моему лучше всего явно привестись в вызывающем
Код
C++ (Qt)
void Test( const char *& src )
{
}
 
int main()
{
char * test = new char[128];
Test((const char *&) test);
return 0;
}
Или нет-нет, "так низзя" ??? Тогда как иначе?


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 05, 2016, 15:05
Указатель =  адрес памяти, в которой хранится адрес объекта
Это уже "указатель на указатель" (**)
Рекомендую неплохую книжку, которая даст понимание отличия указателя от адреса https://www.ozon.ru/context/detail/id/28277147/ (https://www.ozon.ru/context/detail/id/28277147/).

По основной проблеме:
Вы можете завести const char * переменную и передавать её в вашу функцию.


Название: Re: const char *&
Отправлено: Авварон от Декабрь 05, 2016, 15:06
Судя по ошибкам компилятора, полагаю, что в результате неявного преобразования char * в const char * мы получаем rvalue, от которого по стандарту нельзя брать неконстантную ссылку.

Да, вы правы, а я нет:

Код:
typedef char * Ptr;
typedef const char * CPtr;

void Test( const CPtr & src ) {}

int main(int argc, char *argv[])
{
    Ptr src;
    Test(src); // ok
    return 0;
}


Название: Re: const char *&
Отправлено: Авварон от Декабрь 05, 2016, 15:17

Однако ж мы отвлеклись от темы. Как всегда, все проблемы легко решаются если убрать const, но это все-таки не очень хорошо, в ф-ции Test все к месту. По-моему лучше всего явно привестись в вызывающем

Ну только, раз уж на плюсах пишем:
Код
C++ (Qt)
 
int main()
{
char * test = new char[128];
Test(const_cast<const char *&>(test));
return 0;
}

Этот неловкий момент, когда констнантность навешивается, а не убирается.


Название: Re: const char *&
Отправлено: Igors от Декабрь 05, 2016, 15:24
Код:
typedef char * Ptr;
typedef const char * CPtr;

void Test( const CPtr & src ) {}

int main(int argc, char *argv[])
{
    Ptr src;
    Test(src); // ok
    return 0;
}
Так мне не нужна константная ссылка в Test, я затем ссылку и объявил чтобы src менять в ф-ции

По основной проблеме:
Вы можете завести const char * переменную и передавать её в вашу функцию.
Это оглашено в стартовом посте, что еще?


Название: Re: const char *&
Отправлено: Igors от Декабрь 05, 2016, 15:32
В общем, как я понял
Код
C++ (Qt)
void Test( const char *& src );
 
Это НЕконстантная ссылка (на указатель на константу), а значит в момент создания (связывания) ссылки исходный объект точно такого же типа (const char *) должен существовать (lvalue), чтобы он имел адрес. Так или нет?


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 05, 2016, 15:32
Нет. В первом посте оглашено немного другое.

Код
C++ (Qt)
void Test( const char *& src )
{
}
 
int main()
{
char * test = new char[128];
const char * testConst = test;
Test(testConst );
return 0;
}


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 05, 2016, 15:33
В общем, как я понял
Код
C++ (Qt)
void Test( const char *& src );
 
Это НЕконстантная ссылка (на указатель на константу), а значит в момент создания (связывания) ссылки исходный объект точно такого же типа (const char *) должен существовать (lvalue), чтобы он имел адрес. Так или нет?
да


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 06, 2016, 13:32
Согласен.
Покопался в стандарте
Цитировать
8.3.2 References
...
4 It is unspecified whether or not a reference requires storage
Это значит что "замаскированный указатель" может храниться и на регистрах

Это значит, что не определено, требуется или нет память под хранение ссылки. ;)


Название: Re: const char *&
Отправлено: Igors от Декабрь 06, 2016, 13:54
Это значит, что не определено, требуется или нет память под хранение ссылки. ;)
А если не требуется то где же хранить?  :)

Кстати Ваше предыдущее "уточнение" тоже было не совсем удачным
Нет. В первом посте оглашено немного другое.

Код
C++ (Qt)
void Test( const char *& src )
{
}
 
int main()
{
char * test = new char[128];
const char * testConst = test;
Test(testConst );
return 0;
}
Да, это скомпилится, но как с этим работать? Мне-то нужно чтобы Test продвигала (меняла) указатель test. А получив testConst что с ним делать?
Код
C++ (Qt)
test = const_cast<char *> (testConst);
Ну как-то совсем кисло, особенно если вызовов Test много


Название: Re: const char *&
Отправлено: Old от Декабрь 06, 2016, 14:07
Да, это скомпилится, но как с этим работать? Мне-то нужно чтобы Test продвигала (меняла) указатель test. А получив testConst что с ним делать?
Указатель можно будет спокойно двигать, а вот изменить данные по указателю не получиться, вы сами туда const поставили.
Код
C++ (Qt)
void Test( const char *& src )
{
cout << *src++ << endl;
cout << *src++ << endl;
}
 
Так что уточнение было удачным, это вы что-то опять в букваре не дочитали. :)

Ф-ция принимает указатель на константу, сам указатель менять можно, данные по нему - нет. Я этого и хотел, но еще и чтобы сам указатель менялся когда ф-ция отдала упр-е. Напр прочитал слово из строки и продвинул указатель на следующее слово.


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 06, 2016, 14:29
А если не требуется то где же хранить?  :)
Что за тавтология. Если память под хранение не требуется, то и хранить не где, а в операциях подставляем адрес объекта, на который ссылаемся.

Насчёт моего примера, если честно, то я не совсем представляю, где приведённая в #1 конструкция может применяться, не сталкивался, может поведаете, что делает ваша Test?. Вы как-то хотите и вишенку съесть и Ж@#% не ободрать :) . Я бы даже немного перебрал сигнатуру:
Код
C++ (Qt)
const char *Test(const char*)
А лично вам могу посоветовать снять константность с возвращаемого значения :)


Название: Re: const char *&
Отправлено: Igors от Декабрь 06, 2016, 15:06
Насчёт моего примера, если честно, то я не совсем представляю, где приведённая в #1 конструкция может применяться, не сталкивался, может поведаете, что делает ваша Test?.
Упрощенный пример:
Цитировать
"This is text";   // исходная строка
"Thi_ i_ tex_";  // нужно получить
Т.е. в каждом слове заменить последнюю букву на подчеркивание. Вот я и поручу поиск конца слова ф-ции Test, конечно менять содержимое строки ей не положено, поэтому аргумент const. А вот вызывающий менять может/должен.  Как видите, ничего особенного я не хочу.

Я бы даже немного перебрал сигнатуру:
Код
C++ (Qt)
const char *Test(const char*)
А лично вам могу посоветовать снять константность с возвращаемого значения :)
Тогда внутри Test придется писать const_cast :) Ну и сильно много не "вернуть", нередко на входе 2 и больше массивов, которые должны быть "продвинуты".

..не совсем представляю .. не сталкивался..
Тогда может лучше воздержаться от "рекомендую", "советую", и, тем более, грубостей? У меня подобные ситуации возникали неоднократно, и всякий раз я не мог найти четкого решения, всякий раз "приводился", что, конечно, не смертельно, но неприятно. Вот и решил потолковать об этом на форуме, так сказать, "пошлифовать технику"  :)


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 06, 2016, 16:06
В функции спецификатор const немного не согласуется с её назначением, так как она в итоге должна позволять изменять содержимое.
Не хотите возвращать индекс/список индексов окончания слов? Таким образом функция может принимать const char*


Название: Re: const char *&
Отправлено: Old от Декабрь 06, 2016, 17:24
В функции спецификатор const немного не согласуется с её назначением, так как она в итоге должна позволять изменять содержимое.
Не хотите возвращать индекс/список индексов окончания слов? Таким образом функция может принимать const char*
Не, Igors хочет в вызывающей функции иметь не константный указатель, который бы автоматически приводился к const при передачи его в функцию Test.

Код
C++ (Qt)
void Test( const char * &src )
{
   // Здесь указатель можно только двигать, но нельзя менять данные по указателю.
}
 
void foo()
{
   char *buf = ...;
   Test( buf );
   *buf = '_';
}
 
 


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 06, 2016, 17:45
Да я понял, что он хочет. Как раз это и характеризовал в #29 :)
Мне кажется, что по логике функция Test должна позволять редактировать содержимое, на которое указывает src, так как через параметр-ссылку возвращает результат, который будет использован для правки, а не для чтения. Поэтому, для достижения желаемого результата, достаточно в качестве параметра передавать char *&src

Как вариант, на мой взгляд, более читабельный:
Код
C++ (Qt)
std::vector<size_t> Test(const char *&src){
   // поиск индексов конца слов
}
 
void foo(){
   char *buf = ...;
   for (size_t index: Test(buf)){
       buf[index] = '_';
   }
}
 


Название: Re: const char *&
Отправлено: Авварон от Декабрь 06, 2016, 18:38
А еще можно сделать 2 ф-ии - одна берет и возвращает char *, вторая const char*.


Название: Re: const char *&
Отправлено: Igors от Декабрь 07, 2016, 09:12
Мне кажется, что по логике функция Test должна позволять редактировать содержимое, на которое указывает src, так как через параметр-ссылку возвращает результат, который будет использован для правки, а не для чтения.
С какой стати? Чего это ф-ция должна что-то знать/предполагать о том кто/зачем ее использует? А если другой использующий ничего не пишет,  а использует эту ф-цию как часть более сложного поиска где строка всегда неизменяема?

А еще можно сделать 2 ф-ии - одна берет и возвращает char *, вторая const char*.
Если там тельце весомое то все равно сведется к обертке с const_cast. Ну видимо в данном случае это неизбежно

Заметим что и без ссылки не проскочить, напр
Код
C++ (Qt)
void Test( const char ** srcPtr )
 
Те же проблемы и тоже придется привестись


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 07, 2016, 09:30
Мне кажется, что по логике функция Test должна позволять редактировать содержимое, на которое указывает src, так как через параметр-ссылку возвращает результат, который будет использован для правки, а не для чтения.
С какой стати? Чего это ф-ция должна что-то знать/предполагать о том кто/зачем ее использует?
А с такой. Я тоже могу использовать vector::operator[] для просмотра значений и в результате своей работы метод не изменяет члены класса, но он почему-то не константный.


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 07, 2016, 09:50
А еще можно сделать 2 ф-ии - одна берет и возвращает char *, вторая const char*.
Если там тельце весомое то все равно сведется к обертке с const_cast. Ну видимо в данном случае это неизбежно
Можно и без const_cast :) и с версией без изменения содержимого.
Код
C++ (Qt)
const char *Test(const char *str){
return str;
}
 
char *Test(char *str){
const char *constStr = str;
return str + (Test(constStr) - constStr);
}
 
int main() {
char buf[10];
const char buf2[10] = "abc";
Test(buf);
Test(buf2);
 
return 0;
}


Название: Re: const char *&
Отправлено: Igors от Декабрь 07, 2016, 10:19
Можно и без const_cast :) и с версией без изменения содержимого.
Остроумно, но все-таки "с развратом" возможности довольно ограничены. Напр ф-ция ищет какое-то слово входящее в обе строки-аргумента, нормальный дызайн типа
Код
C++ (Qt)
bool FindCommonWord( const char *& str1, const char *& str2 );
 
Тут уже затруднительно написать какой-то код чтобы обойти const_cast. Ну и вообще, чего так уж бояться приведений? Ну нежелательно - да, надо по возможности избегать, но если надо - значит надо, все хорошо в меру


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 07, 2016, 10:39
Тут уже затруднительно написать какой-то код чтобы обойти const_cast. Ну и вообще, чего так уж бояться приведений? Ну нежелательно - да, надо по возможности избегать, но если надо - значит надо, все хорошо в меру
Если хочется, делайте :)
Не забудьте пройтись по памяти ;)
Код
C++ (Qt)
char *Test(const char*);
int main(){
   Test("Hello sigsegv") = '_';
}


Название: Re: const char *&
Отправлено: Igors от Декабрь 07, 2016, 11:17
Если хочется, делайте :)
Не забудьте пройтись по памяти ;)
:)  Ну вообще-то я обычно использую сишное приведение (какой ужас!). А серьезно - все это "академическое программирование" - порядочное фуфло, тут вполне достаточно поддерживать какой-то необходимый уровень грамотности. Учите "специальность", работа там, а не здесь.


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 07, 2016, 11:23
Сказал бы я, что на самом деле фуфло, только боюсь, что снова обидитесь :)


Название: Re: const char *&
Отправлено: Igors от Декабрь 08, 2016, 11:24
Сказал бы я, что на самом деле фуфло, только боюсь, что снова обидитесь :)
Не надо "подымать хвостик" - он у Вас еще очень плохо отрос  :)


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 08, 2016, 11:32
Игорь, завязывайте хвостиками меряться  ;D


Название: Re: const char *&
Отправлено: Igors от Декабрь 08, 2016, 13:07
Да, и кстати
А с такой. Я тоже могу использовать vector::operator[] для просмотра значений и в результате своей работы метод не изменяет члены класса, но он почему-то не константный.
Их 2, если vector константный, то будет вызван константный оператор [], иначе неконстантый


Название: Re: const char *&
Отправлено: __Heaven__ от Декабрь 08, 2016, 13:32
Речь шла о неконстантном варианте перегрузки.