Строковая ссылка из строкового литерала C ++ - PullRequest
0 голосов
/ 15 сентября 2011

Я надеюсь, что кто-нибудь может помочь ответить на вопрос о строках в C ++. Я попытался удалить любой посторонний код отсюда, чтобы он не компилировался (отсутствует пространство имен, определения и т. Д.). Это не проблема "ошибки". Если вам нужны рабочие примеры кода, пожалуйста, укажите, какой код вы хотите (для какого вопроса), я был бы рад изложить что-то более подробное.

//Foo.c
#define EXIT "exit"
Bar* bar; //See question C
//1
foo(const string& text) {
    cout << text;
    bar = new Bar(text); //See question C
}
//2
foo(const char* text) {
    cout << text;
}
//3
foo(string text) {
    cout << text;
}
int main() {
....
    { foo(EXIT); } //braces for scope, see question C)
    bar->print(); //4
....
}

class Bar {
    private const string& strBar;
    Bar::Bar(const string& txt) : strBar(txt) { }
    Bar::print() { cout << strBar; }
}

Если предположить, что только один из трех методов foo () не закомментирован, они не должны быть перегружены. У меня есть пара вопросов здесь:

A) Если бы я мог понять, как использовать OllyDbg достаточно хорошо, чтобы возиться со строковым литералом «exit» в «axit» ПОСЛЕ вызова foo (), я считаю, что вывод все равно будет «exit» в случае 1 и 3, и «выход» в случае 2. Это правильно?

B) В случаях 1 и 3 я полагаю, что, поскольку метод запрашивает строку (даже если это ссылка в случае 1), существует неявный вызов строкового конструктора (он принимает const char *) и этот конструктор ВСЕГДА делает копию, а не ссылку. (см. строковая страница cplusplus.com ). Это правильно (особенно ВСЕГДА)?

C) В случае 1, если я инициализировал новый класс со строкой и атрибутом, которому я назначил текстовую переменную, будет ли эта ссылка указывать на плохую память, когда мы покидаем область? То есть, когда мы достигаем 4, я думаю, что произошло следующее (предполагая, что foo (const string & text) является функцией без комментариев) 1. Временный строковый объект создается для строки foo (EXIT), которая копирует литерал. 2. Ссылка на временный объект передается через bar и атрибуту strBar. 3. Как только код движется дальше и покидает область, в которой был вызван foo (EXIT), я считаю, что объект временной строки выходит из области видимости и исчезает, что означает, что теперь strBar ссылается на область памяти с неопределенным содержимым, думая, что это так. все еще строка.

D) Возвращаясь к A, я верю в случае 2 (foo (const char * text)), что этот вызов foo ссылается на сам литерал, а не на копию, поэтому перебирание литерала в памяти изменит выход. Это правильно? Могу ли я продолжать передавать литерал через (скажем, в Bar), если я продолжаю использовать const char *?

E) Как бы вы протестировали что-либо из этого, помимо "вот как это работает"? и "читать спецификации"? Мне не нужны пошаговые инструкции, но некоторые идеи о том, что я должен был сделать, чтобы самостоятельно ответить на вопрос, используя имеющиеся у меня инструменты (Visual Studio, OllyDbg, предложения для других?), Были бы хорошими. Я потратил немало времени, пытаясь это сделать, и я хотел бы услышать, что люди говорят.

1 Ответ

1 голос
/ 15 сентября 2011

A) Я ничего не знаю о OllyDbg, но во всех случаях std::ostream делает свою собственную копию text до того, как foo вернется, поэтому любое изменение переменных после вызова не повлияет навывод.
B) Да, конструктор string всегда будет делать свою собственную копию char* во время неявного конструирования для параметра.
C) Да, когда вы вызываете foo, a string автоматически создается и используется, и после завершения вызова он уничтожается, и bar указывает на недопустимую память.
D) Вы правы.foo(const char* text) делает копию указателя на данные, но не копирует данные.Но поскольку operator<<(ostream, char*) создает копию данных, изменение данных не повлияет на вывод.Я не понимаю, почему вы не можете передать буквальный символ const char*.
E) Пройдите урок, прочитайте учебник или прочитайте спецификации.Метод проб и ошибок не поможет вам продвинуться в стандартной библиотеке для такого рода вопросов.

Для них концепцией является инкапсуляция.Все объекты в стандартной библиотеке C ++ инкапсулированы, так что вы можете ожидать результатов любой операции, и действительно трудно случайно связать с их внутренними компонентами, чтобы вызвать сбои или утечку.Если вы скажете ostream напечатать данные на char *, он (A) сделает это немедленно или (B) сделает свою собственную копию, прежде чем она вернется в случае, если вы связываетесь с char* позже.

...