2014-01-24 3 views
1

Я пытался найти код Скотта Мейерса Эффективный C++, пункт 3 в частности.Указатель ошибки сегментации на ссылку

Код в своей книге должен быть очень похож на это (он ушел из конструктора)

#include <iostream> 


class TextBlock { 
public: 
    TextBlock(char* ptr) : ptrText(ptr) 
    {} 
    char& operator[](std::size_t pos) const { 
     return ptrText[pos]; 
    } 
private : 
    char* ptrText; 
}; 

int main(int argc, char* argv[]) { 
    const TextBlock block("Hello"); 
    std::cout << block[0] << std::endl; 
    char* ptr = &block[0]; 
    *ptr = 'J'; 
    std::cout << block[0]; 
} 

В момент, когда я изменить содержимое в указатель PTR (* PTR = «J»;) , Я получаю ошибку сегментации (что обычно происходит при разыменовании неинициализированного или освобожденного указателя). Это не происходит здесь, что происходит не так на *ptr = 'J';

+0

Указатель на ссылку невозможно. – chris

+0

@MikeSeymour, так же, как не имеет значения, как заголовок;) – chris

+0

@chris: К сожалению, я не заметил названия. –

ответ

4

TextBlock не имеет хранилища. Он указывал на постоянную строку в памяти "Hello", и вы попытались изменить содержимое только для чтения.

Если вы объявили локальную переменную с его собственной памяти, это будет работать, например:

char test[32] ; 
strcpy(test, "Hello") ; 
const TextBlock block(test) ; 
char * ptr= &block[0] ; 

*ptr= 'J' ; 
0
#include <iostream> 


class TextBlock { 
public: 
    TextBlock(char* ptr) : ptrText(ptr) 
    {} 
    char& operator[](std::size_t pos) const { 
     return ptrText[pos]; 
    } 
private : 
    char* ptrText; 
}; 

int main(int argc, char* argv[]) { 
    char text[] = "Hello"; 
    const TextBlock block(text); 
    std::cout << block[0] << std::endl; 
    char* ptr = &block[0]; 
    *ptr = 'J'; 
    std::cout << block[0]; 
} 
0

да это правда! ptrText просто записывает ptr «hello», а «hello» - это постоянный статический текст, который вы не можете изменить. Он ничего не хранил, поэтому вы не можете его изменить.

1

Вы должны управлять

ptrText

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

вы можете использовать массив символов вместо

#include <iostream> 

#define MAX_LENGTH = 1024 

class TextBlock { 
public: 
TextBlock(char* ptr) 
{ 
    memset(ptrText, 0, MAX_LENGTH); 
    memcpy(ptrText, ptr, strlen(ptr) < MAX_LENGTH?strlen(ptr):MAX_LENGTH); 
} 

char& operator[](std::size_t pos) const { 
    return ptrText[pos]; 
} 
private : 
char ptrText[MAX_LENGTH]; 

};

Смежные вопросы