С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.81/21: Рейтинг темы: голосов - 21, средняя оценка - 4.81
23 / 2 / 0
Регистрация: 24.04.2011
Сообщений: 66

Null pointer assignment.

24.08.2011, 00:20. Показов 4685. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. Такая проблема: Пытаюсь вызвать функция класса Up()
s2 = s1.up(), возвращая указатель на строку (по-умолчанию в s2 пустая строка имеет адрес NULL).
Вот только почему передается не ссылка, а само значение строки, поскольку компилятор пишет: null pointer assignment. Значит ссылка не поменялась, и он, не выделив память, прострочил прямо с нулевого адреса...
И второй вопрос, как можно в данном случае все-таки передать значение (хотя первый вопрос в силе), но так, чтобы выделить точное кол-во памяти под передаваемую строку в s2?
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
#include "iostream.h"
#include "CONIO.h"
#include "Ctype.h"
#include "string.h"
using namespace std;
class String
{
 private:
  char* st;
 public:
  String(): st(NULL) {}
  String(char* str) {int len = strlen(str);
             st = new char[len+1]; strcpy(st, str);
            }
  ~String() {delete st;}
  void show()const {cout<<endl<<st;}
  String up() {int len = strlen(st);
           for(int i=0; i<len; i++) st[i] = toupper(st[i]); return st;
          }
};
///////////////////
int main()
{
 String s1 = "Test yes TEsT";
 String s2;
 s2 = s1.up();
 s2.show();
 getch();
return 0;
}
Заранее благодарен!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.08.2011, 00:20
Ответы с готовыми решениями:

Null pointer assignment
Помогите найти ошибку, при заполнении массива вручную в конце выдает - Null pointer assignment. И еще вопрос, как сделать чтобы после...

Ошибка Null pointer assignment
Помогите, пожалуйста, кто знает. BC++ 3.11 выдает 'Null pointer assignment'. Я, в принципе, в курсе, что это из-за того, что я...

Error null pointer assignment
Помогите, программа, которая создает вектор элементы которого равны сумме положительных элементов столбца массива, в конце выводит null...

25
Эксперт С++
 Аватар для grizlik78
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
24.08.2011, 00:46
Проблема вот в чём.
В строке 26 функция up() создаёт временный объект String (из указателя). Дальше этот временный объект используется для создания s2 с помощью конструктора копирования. Затем временный объект уничтожается.
А теперь сама проблема: конструктор копирования, созданный компилятором, копирует только указатель, но не само содержимое строки. После удаления временного объекта копия указателя в новом объекте указывает на уже удалённую область памяти.
Выход: определить свой конструктор копирования, который будет осуществлять "глубокое копирование", то есть скопирует не указатель, а саму строку.

Добавлено через 15 минут
Цитата Сообщение от Stalin45 Посмотреть сообщение
возвращая указатель на строку
Цитата Сообщение от Stalin45 Посмотреть сообщение
Вот только почему передается не ссылка, а само значение строки
Ну во-первых всё-таки указатель, а не ссылку.
Во вторых, функция объявлена как возвращающая String, поэтому создаётся временный оъект. А поскольку конструктор объявлен без explicit, то осуществляется неявное преобразование из указателя.
Проблема должна уйти, если объявить функцию up() как возвращающую указатель, но тем не менее конструктор копирования для такого класса в любом случае нужен.

Добавлено через 2 минуты
И ещё, в конструктор было бы правильнее принимать указатель на константную строку, то есть
C++
1
String(const char* str)
или
C++
1
String(char const* str)
что одно и то же.
1
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
24.08.2011, 02:33
Класс, в котором конструктор динамически запрашивает память, обязан реализовать: конструктор копирования, деструктор, операцию присваивания. Остальное - по необходимости.
1
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
24.08.2011, 08:12
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
обязан реализовать
Либо запретить их использование помещением их определения в private.
2
23 / 2 / 0
Регистрация: 24.04.2011
Сообщений: 66
24.08.2011, 13:34  [ТС]
grizlik78, огромное спасибо за разъяснение механизма возврата (я считал, что функция up() возвращает объект объект String, через который и запускалась функция изначально, а не создает временный и недолговечный. Это многое объясняет!).

Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Класс, в котором конструктор динамически запрашивает память, обязан реализовать: конструктор копирования, деструктор, операцию присваивания. Остальное - по необходимости.
Операция присваивания...если я правильно понял, то это перегрузка operator= (никогда раньше не использовал).
Попробовал динамически выделить память:
C++
1
2
3
4
5
  String operator= (const String* s1) {int len = strlen(s1->st);
                       st = new char[len+1];
                       strcpy(st, s1->st);
                       return String(st);
                      }
Как всегда все работает, однако в конце все ещё надпись: Null poinet assignment.
Но ведь на этот раз память выделена! Быть может эта надпись появляется даже когда просто NULL адрес был присвоен, но значение в нем не изменено?
C++
1
  String(): st(NULL)
C++
1
2
3
 String s2;
 s2 = s1;
 s2.show();
0
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
24.08.2011, 13:40
Цитата Сообщение от Stalin45 Посмотреть сообщение
однако в конце все ещё надпись: Null poinet assignment.
Так и ошибка никуда не делась.)
Возвращать нужно не String, а String&
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
24.08.2011, 13:40
Stalin45, Сигнатура оператора неверная.

C++
1
String& operator= (const String& s1);
1
23 / 2 / 0
Регистрация: 24.04.2011
Сообщений: 66
24.08.2011, 13:45  [ТС]
Вот я дурак, я же не указатели на String присваиваю друг другу, а обычные объекты!! Т.е. моя функция operator= (String* s1) даже не вызывалась...
Получилось решить проблему строкой:
C++
1
 s2 = &s1
но, верно, в данном случае удобнее изменить сам operator=
Спасибо!
0
Эксперт С++
 Аватар для grizlik78
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
24.08.2011, 13:45
Кстати да, я почему-то рассказал про конструктор копирования, хотя в данном случае используется операция присваивания. Ну да не суть, они оба должны быть определены.
И помимо неправильной сигнатуры есть ещё маленькая деталь — в операторе присваивания стоит проверять на присваивание самому себе (это в данном случае не важно, но всё-таки), а ещё перед присваиванием удалять старое содержимое.
1
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
24.08.2011, 13:50
Герб Саттер приводит много более элегантную реализацию операции присваивания:
C++
1
2
3
4
5
6
Листинг 3.12. Реализация операции присваивания "по Саттеру"
TArray& TArray::operator=(const TArray &t)
{ TArray temp(t);       // временнный локальный объект temp = t
  Swap(temp);           // обмен полями с текущим объектом
  return *this;             // возврат текущего объекта
}                   // temp уничтожен
Swap - это функция обмена. Часто можно использовать std::swap().
1
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
24.08.2011, 15:11
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
много более элегантную реализацию операции присваивания
Причём, устраняющую проблему самоприсваивания.
Но там ещё есть условие, что Swap должна быть бессбойной.
1
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
24.08.2011, 15:24
Цитата Сообщение от Deviaphan Посмотреть сообщение
Причём, устраняющую проблему самоприсваивания.
Но там ещё есть условие, что Swap должна быть бессбойной.
Да. И стандартная swap этому удовлетворяет.
Поэтому я практически всегда стараюсь использовать вариант Саттера - писать меньше...
1
Делаю внезапно и красиво
Эксперт С++
 Аватар для Deviaphan
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
24.08.2011, 15:26
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
И стандартная swap этому удовлетворяет.
Не удовлетворяет. Если у объекта нет бессбойного конструктора копирования и деструктора, то не удовлетворяет.
2
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
24.08.2011, 16:05
Цитата Сообщение от Deviaphan Посмотреть сообщение
Не удовлетворяет. Если у объекта нет бессбойного конструктора копирования и деструктора, то не удовлетворяет.
Спасибо за напоминание...
1
Заблокирован
24.08.2011, 21:22
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Герб Саттер приводит много более элегантную реализацию операции присваивания:
C++
1
2
3
4
5
6
Листинг 3.12. Реализация операции присваивания "по Саттеру"
TArray& TArray::operator=(const TArray &t)
{ TArray temp(t);       // временнный локальный объект temp = t
  Swap(temp);           // обмен полями с текущим объектом
  return *this;             // возврат текущего объекта
}                   // temp уничтожен
Swap - это функция обмена. Часто можно использовать std::swap().
Нельзя использовать std::swap, так как в вашем примере используется синтаксис для вызова функции swap - члена класса.

Добавлено через 7 минут
Цитата Сообщение от Stalin45 Посмотреть сообщение
Здравствуйте. Такая проблема: Пытаюсь вызвать функция класса Up()
s2 = s1.up(), возвращая указатель на строку (по-умолчанию в s2 пустая строка имеет адрес NULL).
Вот только почему передается не ссылка, а само значение строки, поскольку компилятор пишет: null pointer assignment. Значит ссылка не поменялась, и он, не выделив память, прострочил прямо с нулевого адреса...
И второй вопрос, как можно в данном случае все-таки передать значение (хотя первый вопрос в силе), но так, чтобы выделить точное кол-во памяти под передаваемую строку в s2?
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
#include "iostream.h"
#include "CONIO.h"
#include "Ctype.h"
#include "string.h"
using namespace std;
class String
{
 private:
  char* st;
 public:
  String(): st(NULL) {}
  String(char* str) {int len = strlen(str);
             st = new char[len+1]; strcpy(st, str);
            }
  ~String() {delete st;}
  void show()const {cout<<endl<<st;}
  String up() {int len = strlen(st);
           for(int i=0; i<len; i++) st[i] = toupper(st[i]); return st;
          }
};
///////////////////
int main()
{
 String s1 = "Test yes TEsT";
 String s2;
 s2 = s1.up();
 s2.show();
 getch();
return 0;
}
Заранее благодарен!
У вас тут несколько ошибок. первое - у вас не определен конструктор копирования. Второе - у вас нет определения оператора присваивания. Третье - в деструкторе вы вместо delete выражения должны использовать delete [] выражение, так как вы должны удалить массив. Четвертое - в функции up вы не делаете проверку на то, что ваш указатель равен NULL.

Саму функцию up можно написать проще.

C++
1
2
3
4
5
6
7
8
9
String String::up() const
{
   if ( st )
   {
      while ( *st ) *st = toupper( *st );
   }
 
   return ( st );
}
1
Эксперт С++
 Аватар для grizlik78
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
24.08.2011, 21:26
Цитата Сообщение от Сыроежка Посмотреть сообщение
while ( *st ) *st = toupper( *st );
infinite loop detected.
0
Заблокирован
24.08.2011, 21:29
Цитата Сообщение от grizlik78 Посмотреть сообщение
infinite loop detected.
И как вы определили infinite loop, не подскажите?
0
Эксперт С++
 Аватар для grizlik78
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
24.08.2011, 21:30
Глазами. Где переход к следующему символу?
0
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
24.08.2011, 21:31
Цитата Сообщение от Сыроежка Посмотреть сообщение
И как вы определили infinite loop, не подскажите?
Элементарно, Ватсон!... указатель не изменяется...
0
Заблокирован
24.08.2011, 21:33
Цитата Сообщение от grizlik78 Посмотреть сообщение
Глазами. Где переход к следующему символу?
Спасибо. Исправлю.

C++
1
2
3
4
5
6
7
8
9
String String::up() const
{
   if ( st )
   {
      for ( ; *st ; ++st ) *st = toupper( *st );
   }
 
   return ( st );
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.08.2011, 21:33
Помогаю со студенческими работами здесь

Null pointer
void C_StringBit :: setStrBit() { char* ptr1; cout &lt;&lt; &quot;Введите строку&quot;&lt;&lt; endl; cin &gt;&gt; ptr1; lengthBit = strlen(ptr1); ...

Invalid null pointer
Так она работает: #include &lt;iostream&gt; #include &lt;conio.h&gt; #include &lt;list&gt; #include &lt;string&gt; using namespace std; void...

string, invalid null pointer
#include &lt;stdio.h&gt; #include &lt;iostream&gt; #include &lt;string&gt; using namespace std; #define SIZE 450 ...

Ошибка компиляции: invalid null pointer
Не могу понять, в чем проблема.. Кто знает? #include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &quot;list.h&quot; using namespace...

Что делать, если "просят" разыменовать null-pointer?
Есть код примерно следующего содержания: class Foo { private: int *ptr; public: int&amp; operator*() { ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru