константный указатель, назначенный указателю - PullRequest
13 голосов
/ 23 июля 2010

Почему я не могу этого сделать:

char* p = new char[10];

void SetString(char * const str)
{
    p = str;
}


SetString("Hello");

У меня есть константный указатель на символ, почему я не могу присвоить константный указатель другому указателю?

Это просто кажется нелогичнымТак как, присваивая его другому указателю, вы по сути не нарушаете постоянство указателя на символ.Или вы?

РЕДАКТИРОВАТЬ: Когда я компилирую это, он говорит "ошибка C2440: '=': не может преобразовать из 'char * const * __ w64' в 'char *'"

(IЯ пытаюсь понять концепцию из книги, которую я читаю. Просто не могу получить код для компиляции.

КОД:

int _tmain(int argc, _TCHAR* argv[])
{

    MyString *strg = new MyString(10);
    strg->SetString("Hello, ");

    MyString *secondstr = new MyString(7);
    secondstr->SetString("Tony");

    strg->concat(*secondstr, *strg);

}

ФАЙЛ CPP:

#include "MyStringClass.h"
#include <string.h>
#include "stdafx.h"

#include "MyStringClass.h"

void MyString::concat(MyString& a, MyString& b)
{
    len = a.len + b.len;
    s = new char[len + 1];
    strcpy(s, a.s);
    strcat(s, b.s);
    delete [] s; 

}

void MyString::SetString(char * const str)
{
    s = str;
}

MyString::MyString(int n)
{
    s = new char[n+1];
    s[n+1] = '\0';
    len = n;
}

ФАЙЛ ГОЛОВКИ:

#include <string.h>
#include <stdio.h>

class MyString
{
private:
    char* s;
    int len;
public:
    MyString(int n = 80);

    void SetString (char * const str);

    void concat (MyString& a, MyString& b);
};

1 Ответ

19 голосов
/ 23 июля 2010

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

int * const const_pointer = &some_int_var; // will be always pointing to this var
const_pointer = &some_other_var; // illegal - cannot change the pointer
*const_pointer = 2; // legal, the pointer is a pointer to non-const

Указатель на константу - это указатель, значение которого нельзя изменить:

const int * pointer_to_const = &some_int_var; // doesn't have to be always pointing to this var
pointer = &some_other_var; // legal, it's not a constant pointer and we can change it
*pointer = 2; // illegal, pointed value cannot be changed

Вы всегда можете присвоить константу переменной, то есть постоянный указатель на неконстантный указатель (а). Вы можете привести указатель к неконстантному указателю на const (b). Но вы не можете привести указатель к const к указателю на non-const (c):

int * pointer;
int * const const_pointer = &var;
const int * pointer_to_const;

/* a */
pointer = const_pointer; // OK, no cast (same type)

/* b */
pointer_to_const = pointer; // OK, casting 'int*' to 'const int*'

/* c */
pointer = pointer_to_const; // Illegal, casting 'const int*' to 'int*'

[EDIT] Ниже это не стандартный c ++. Однако это обычное дело. [/ EDIT]
Строковый литерал

"Hello"

преобразуется в постоянный указатель в const (const char * const):

char *pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*'
char * const const_pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*'
const char * pointer_to_const = "Hello"; // OK, we can assign a constant to a variable of the same type (and the type is 'const char*')
"Hello" = pointer_to_const; // Illegal cannot re-assign a constant

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

Резюме:
1) Если вы приведете указатель одного типа к указателю другого типа, вы не сможете привести указатель к константе к указателю на неконстант.
2) Если у вас есть указатель на константу, то применяются те же правила, что и для других констант: вы можете назначить константу переменной, но не можете присвоить переменную константе (кроме ее инициализации).

// РЕДАКТИРОВАТЬ
Как указал GMan, стандарт C ++ 98 (§4.2 / 2) позволяет неявно приводить строковые литералы (которые являются константными массивами символов) к неконстантному символьному указателю. Это из-за обратной совместимости (в языке C нет констант).

Конечно, такое преобразование может привести к ошибкам, и компиляторы нарушат правило и покажут ошибку. Однако GCC в режиме совместимости показывает только предупреждение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...