C ++ char * указатель на функцию и удаление - PullRequest
4 голосов
/ 01 июля 2010

У меня есть следующий код:

#include <iostream>
using namespace std;

void func(char * aString)
{
    char * tmpStr= new char[100];
    cin.getline(tmpStr,100);
    delete [] aString;
    aString = tmpStr;
}

int main()
{
    char * str= new char[100];
    cin.getline(str,100);
    cout<< str <<endl;
    func(str);
    cout<< str <<endl;
    return 0;
}

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

Ответы [ 11 ]

12 голосов
/ 01 июля 2010

Как сказал GregS, упрощенный ответ - объявить вашу функцию по ссылке:

void func(char *&aString)

Однако это не совсем лучшее решение.В C ++ вы обычно избегаете простых массивов и используете контейнеры.

#include <iostream>
#include <string>

void func(std::string &s)
{
    std::getline(std::cin, s);
}

int main()
{
    std::string str;
    func(str);
    std::cout << str << std::endl;
    return 0;
}
6 голосов
/ 01 июля 2010

Потому что второй cout напечатает то, на что указывает str. И str, указатель в вашей главной функции будет иметь одинаковое значение до и после вызова func.

Действительно, в функции func вы меняете значение переменной aString. Но это другая переменная, чем str в main.

Если вы хотите, чтобы значение str было изменено, вы должны передать его func по ссылке или по указателю. (Обратите внимание, что вы пишете, чтобы передать символы по указателю. Я имею в виду, что вы должны передать указатель по указателю: void func(char **str_ptr) или по ссылке void func(char *&str_ref))

Если вы действительно делаете C ++, вы должны использовать std :: string вместо старых строк C.

Пример передачи указателя по указателю:

func(char ** aString)
{
    char * tmpStr= new char[100];
    cin.getline(tmpStr,100);
    delete [] *aString;
    *aString = tmpStr;
}

Плюс вы должны назвать это так: func(&str);

2 голосов
/ 01 июля 2010

Измените func на

void func(char * aString)
{
    cin.getline(aString,100);
}

, и это работает, по крайней мере, для меня.

2 голосов
/ 01 июля 2010

Когда func () вызывается из main (), значение указателя str передается функции (это делается путем копирования его значения в стек)

Значение, котороебыл сохранен в стеке, когда вызов func () становится локальной переменной aString внутри func ().Вы можете изменить это значение, но как только func () вернет все его локальные переменные, они будут отброшены.Значение aString не будет скопировано обратно в строку .

Чтобы ваш код работал, вы должны либо:

  • Использовать буфер, на который указывает aStringдля чтения данных: cin.getline ( aString , 100);или
  • Передать указатель на указатель: void func (char ** aString)
1 голос
/ 01 июля 2010

Указатель передается по значению.Да, вы можете изменить содержимое того, на что указывает этот указатель, но при выходе из функции старый адрес сохраняется.Следовательно, "aString = tmpStr";становится бесполезным и "char * tmpStr = new char [100];"создает утечку памяти.Вам нужно передать указатель по ссылке:

void func(char*& aString)
{
    char * tmpStr= new char[100];
    cin.getline(tmpStr,100);
    delete [] aString;
    aString = tmpStr;
}
1 голос
/ 01 июля 2010

Если ваша цель на самом деле прочитать строку с клавиатуры, сделайте это:

std::string foo;

std::getline(std::cin, foo);

В противном случае, когда вы передаете указатель на функцию, указатель передается по значению . Это означает, что вы не можете изменить сам указатель из функции, но вы можете изменить объект, на который он указывает. В C ++ вы можете сделать это следующим образом:

void bar(std::string & s) {
    std::getline(std::cin, s);
}

// in calling code
    std::string foo;

    bar(foo);

Это передает ссылку на строку в функцию. Теперь функция может изменять содержимое строки.

Если вы хотите написать функцию, которая выделяет некоторую память для сохранения результата, сделайте это следующим образом:

boost::shared_array<char> foo() {
    boost::shared_array<char> result(new char[100]);
    std::cin.getline(result.get(), 100);
    return result;
}
0 голосов
/ 01 июля 2010

Указатель aString, который вы передаете func (), указывает, где (по какому адресу) вы можете прочитать и написать строку str. Когда вы говорите aString = tempStr, вы заменяете его исходное значение (адрес строки, на который указывает str), новым значением (адрес строки, на который указывает tempStr). Это не заставит str указывать на то же место, что и tempStr.

Представь, что я дам тебе лист бумаги с домашним адресом моего друга. Затем выцарапаете его и пишете на нем адрес вашего брата (который живет в Лондоне). Если я тогда решу навестить своего друга, я не пойду в Лондон, даже если у вас будет лист бумаги с надписью «Друг Павла: 123 Лондона».

Чтобы заставить main распечатать строку, введенную вами в func (), вы можете либо скопировать входную строку в aString (вы переместили брата в дом моего друга), либо передать указатель или ссылку на str (пусть я дам вам мою адресную книгу, чтобы вы могли изменить запись для моего друга в Лондон). В любом случае, в следующий раз, когда я приеду в «дом моего друга», там будет ваш брат.

0 голосов
/ 01 июля 2010
#include <iostream>

void func(std::istream& is, std::string& aString)
{
    std::getline(is, aString);
}

int main()
{
    std::string str;
    std::getline(std::cin, str);
    if(std::cin)
        std::cout<< str << '\n';
    std::string str;
    func(std::cin, str);
    if(std::cin)
        std::cout<< str << '\n';
    return 0;
}
0 голосов
/ 01 июля 2010

Вам нужно передать str в качестве ссылки.

0 голосов
/ 01 июля 2010

Строка aString = tmpStr просто меняет значение astring (то есть адрес / указатель) на другое значение (то есть другой адрес / указатель), но не на содержание памяти, на которую указывает aString.

Вы можете попытаться изменить подпись на:

void func(char ** aString)

И изменить две последние строки func на:

delete [] *aString;
*aString = tmpStr;

Таким образом, последняя строка вызываетпрограмма для изменения адреса , хранящегося в памяти, на которую указывает aString, на вновь выделенный адрес (tmpStr).(Я знаю, это ошеломляет.)

А затем позвоните через

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