Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > В чём косяк?


Автор: cia 7.4.2016, 00:38
Изучаю с++, поэтому вопрс может быть наивным...
Вот такой код:
Код

char* foo(int i) {
    char str[5];
    itoa(i,str,10);
    char* p=str;
//    return p=str;
    return str;
}

int main(int argc, char **argv) {
    char *s=foo(9);
    cout << s << endl;
    return 0;
}


В консоль пишет пустую строку. Но если расскоментировать "return p=str", то выводит "9". Объясните, пожалуйста, почему так, по моему представлению о мире результат должен быть одинаков.

Автор: disputant 7.4.2016, 13:55
Что так, что эдак - так поступать нельзя: str - это локальный массив, создаваемый в стеке, и после выхода из функции его больше нет. Да, память может остаться не поврежденной (какое-то время) - но это как раз плохо - ошибка не сразу выплывет.

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

Автор: xvr 7.4.2016, 13:56
Вы вернули из функции foo указатель на локальную переменную, которая была разрушена при выходе из функции. Так что вам очень повезло, что
Цитата(cia @  7.4.2016,  00:38 Найти цитируемый пост)
Но если расскоментировать "return p=str", то выводит "9".


Добавьте слово static перед  char str[5];, будет работать

Автор: borisbn 7.4.2016, 14:17
Цитата(cia @  7.4.2016,  00:38 Найти цитируемый пост)
Изучаю с++,

а используете конструкции Си (кстати, в перемешку с Си++).
Пользуйтесь std::string для строк. И никаких "сырых" указателей.

Автор: borisbn 7.4.2016, 14:43
На Си++ Ваш код выглядел бы так

Код
#include <iostream>
#include <string>
#include <sstream>

std::string foo( int i ) {
// С использованием С++11
    return std::to_string( i );
// Без использования С++11
    std::stringstream ss;
    ss << i;
    return ss.str();
}

int main()
{
    std::string s = foo( 9 );
    std::cout << s << std::endl;
}

Автор: cia 9.4.2016, 13:42
Большое спасибо за ответы, разобрался что к чему.
Что бы не плодить темы с подобного рода вопросами, задам ещё один тут...

Вот такой простенький код (всё лишнее убрал):
Код

class StringsWork {
private:
    char *_str;
public:
    StringsWork();
    StringsWork(char *s);
    void operator =(char *);
};

int main() {
//    StringsWork story("D");
    StringsWork story();
    story="У Лукоморья дуб зелёный;\n";
    return 0;
}


Если использовать первый конструктор (который закоментирован), то работает как надо. Но со вторым компилятор ругается:
assignment of function 'StringsWork story()'
cannot convert 'const char [26] to 'StringsWork()'

Мне не понятно поведение компилятора, разъясните, пожалуйста. Что это за приведение типа к StringsWork, ведь в обоих случаях должен "срабатывать" перегруженный оператор "=", которй ожидает параметр char* и который ничего не должен возвращать. Тоесть в строке
story="asdf";
Реального присвоения адреса не происходит, а происходит вызов метода "operator =". Разве нет?

Автор: borisbn 9.4.2016, 15:57
Цитата(cia @  9.4.2016,  13:42 Найти цитируемый пост)
StringsWork story();

Это - объявление фунции, с именем story, которая возвращает StringsWork.
Это называется https://en.wikipedia.org/wiki/Most_vexing_parse

Автор: cia 9.4.2016, 18:51
Если честно, понятней не стало  smile 
Я пишу так:
Код

StringsWork *story=new StringsWork();

Теперь story - это StringsWork*. Но проблема всё та же, на этой строке:
Код

story="У Лукоморья дуб зелёный;\n";


Тут компилятор ругается, что не может привести const char* к StringsWork*, как будто не замечая перегруженный "operate =".

Автор: xvr 9.4.2016, 19:46
Цитата(cia @  9.4.2016,  18:51 Найти цитируемый пост)
Если честно, понятней не стало

В языке есть правило - если что то похоже на объявление функции, то это и есть объявление функции. StringsWork story(); похоже на прототип (объявление) функции с именем story и без параметров, возвращающую экземпляр класса StringsWork. Т.е. это именно объявление функции, а не переменной story типа StringsWork с пустым списком параметров конструктора.

Цитата(cia @  9.4.2016,  18:51 Найти цитируемый пост)
Тут компилятор ругается, что не может привести const char* к StringsWork*, как будто не замечая перегруженный "operate =". 

Правильно ругается, и перегрузка не поможет - вы же перегрузили оператор для класса, а не для указателя на класс. Делайте так:
Код

*story="У Лукоморья дуб зелёный;\n";

Автор: cia 11.4.2016, 11:49
Спасибо за разъяснение. При помощи поддержки гугла разобрался что к чему ))

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)