Возможна ли инициализация const-строки не в конструкторе?
===========================================================

 Такой вопрос.  
  

У меня есть некий класс со строковым полем (unsigned char* str). Это поле инициализируется не в конструкторе, а в одном из методов класса. Хотелось бы сделать поле (unsigned char* const), чтобы при вызове его get-функции был можно было получить указатель на данную строку, но не давать возможность изменять данные, которые были записаны при инициализации.  
  
  

Существует ли какой-нибудь способ это сделать малой кровью? Если все оставлять как есть, то компилятор ругается на то, что инициализации при объявлении и в конструкторе нет. Если добавить ее в конструктор (str = NULL), то затем, соответственно, данные менять будет уже невозможно.   
  
  

Плюс к тому, есть такая ремарка, инициализация происходит следующим образом:  
  
  

В методе получается указатель на TCHAR*, который затем преобразуется к char*, который явно кастуется в unsigned char*. Получив указатель на данную строку (она временная и имеет смысл только в рамках инициализатора), вызывается str = new [*длина строки*]; а затем memcpy копирует одно в другое. Таким образом, происходит двойное присвоение, сначала str = new, затем memcpy(str,...). Можно ли прямо здесь умереть с мечтой иметь константные данные?  
  
  

P.S. std::string не используется намеренно. Но если других вариантов нет, замена на него возможна, но желательно, чтобы get-метод все равно возвращал unsigned char* const.  
  
  

Заранее спасибо за помощь. 

 Краткий ответ на вопрос из названия — нет, нельзя. Но если я правильно понял задачу — избежать возможности модификации, то решений можно придумать несколько — отдавать копию по значению (тут хорошо подойдёт std::string), принимать в get параметром указатель на строку-приёмник и копировать туда, копировать в константный буфер, созданный тут же на стеке и отдавать указатель на него… 

 const члены, а также члены, являющиеся references, обязательно инициализировать в конструкторе. 

 Не совсем понятно, почему константным должен стать указатель, если хочется запретить менять записанные по нему данные, а не его самого. То ли неточность в описании, то ли хотел сказать не unsigned char* const, а const unsigned char*. Но независимо от этого, атрибут const можно обойти модификатором const\_cast (или банальным Си-подобным приведением типа). Главное при этом, чтобы приводимая память не оказалась в read-only области, но если она явно выделяется по new, то такого казуса, по идее, произойти не должно. 

 unsigned char* const — это константный указатель на изменяемый массив char  

  

вам нужен  

  

const unsigned char * — неконстантный указатель на неизменяемый массив char  

  

тогда вы сможете изменять значение указателя внутри класса (если ваше поле приватное), но никто не сможет изменять сами данные (без const\_cast).  

  

пруф: [habrahabr.ru/post/100104/](http://habrahabr.ru/post/100104/) 

 >> Таким образом, происходит двойное присвоение, сначала str = new, затем memcpy(str,...).  

никакого двойного присваивания не происходит  

  

str = new unsigned char[size];  

  

только выделяет память и запоминает, где эта память выделена, сама память не инициализируется.  

  

копирование данных происходит внутри memcpy.  

  

справедливости ради, если у вас typeof( str ) == typeof( usigned const char * ), то вы не сможете вызвать memcpy без приведения типа, т.к. у вас указатель на неизменяемые данные.  

  

вам надо:  

  

class A  

{  

private:  

unsigned const char *str;  

A(): str( nullptr ) // можно и не инициализировать в принципе, если уверены,  

 // что не будете читать его до инициализации  

{  

}  

init(… )  

{  

 unsigned char *ptr = new unsigned char[size];  

 memcpy( ptr,… );  

 str = ptr; // сами данные вы тут не меняете, только указатель на данные  

}  

usigned const char *get() const{ return str; }  

};