2012-04-11 3 views
5

У меня есть несколько вопросов, которые я думаю, будет довольно легко для кого-то с C++ опыт, чтобы ответить, я буду смелым в quesitons для TL; DRC-Style струнам STD :: строка преобразования осветление

Учитывая следующий код:

void stringTest(const std::string &s) 
{ 
    std::cout << s << std::endl; 
} 

int main() 
{ 
    stringTest("HelloWorld"); 
} 

Hopefuly кто-то может указать на ошибки в моей мысли процесс здесь:

Почему параметр в stringTest должны быть отмечены сопзЬ при передаче строки C-Style? Не существует ли неявное преобразование в std :: string, которое происходит с использованием его конструктора строки cstyle, поэтому «s» больше не является ссылкой на литерал (и не обязательно является константой).

Кроме того, что б cstyle строка конструктор выглядеть, и как компилятор знает, чтобы вызвать это, увидев:

stringTest("HelloWorld"); 

ли просто признать строковый литерал быть что-то вроде полукокса * ?

Я наткнулся на эти вопросы, изучая конструкторы копирования. Еще один быстрый quesiton для собственного очищения ...

В случае что-то вроде:

std::string s = "HelloWorld"; 

ли конструктор cstyle строки используется для создания экземпляра временных зОго :: строки, а затем временная строка скопирован в «s» с использованием конструктора строковых копий?:

std::string(const std::string&); 
+0

«Почему параметр в stringTest должен быть помечен как const?» - независимо от того, когда он не нужен, вы хотите создать _all_ ссылки 'const', которые фактически не изменены. – leftaroundabout

+0

@leftaroundabout: Справедливая точка зрения, я непременно возьму это близко к сердцу. – Riken

+0

Возможный дубликат [Как ссылка, не связанная с константой, не может привязываться к временному объекту?] (Http://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to -a-time-object) –

ответ

2

Почему параметр в stringTest должны быть отмечены сопзЬ, когда передается строка C-Style?

Он имеет только тогда, когда параметр является ссылкой, поскольку временный std::string строится из char const* вы передаете в и не- const ссылки на временный, является незаконной.

Он просто распознает строковый литерал как нечто вроде char *?

Строковый литерал представляет собой массив char const, который распадается на char const*. Из этого компилятора следует, что он должен использовать конструктор explicitstd::string::string(char const *) для создания временного.

Является ли конструктор cstyle для создания временной std :: string, а затем временная строка копируется в «s» с использованием конструктора строковых копий?

Это немного сложнее, чем это. Да, создается временное. Но конструктор копирования может или не может быть вызван; компилятору разрешено пропустить построение копии как оптимизацию.Конструктор копирования должен еще быть обеспечен, хотя, так что следующий не скомпилируется:

class String { 
    String(char const *) {} 
    private: 
    String(String const &); 
}; 

int main() 
{ 
    String s = ""; 
} 

Кроме того, в 11 конструктора перемещения C++ будет использоваться, если это предусмотрено; в этом случае конструктор копирования не требуется.

+0

+1, но вы можете (должны) пояснить, что в третьем случае, хотя конструктор копирования * требуется *, он фактически не вызывается, потому что он (всегда - независимо от оптимизации?) должен быть удален , Это довольно важно, хотя это «просто» разрешенная оптимизация. –

+0

Строковый литерал не имеет 'char const *', это 'char const [N]', который, конечно, неявно конвертируется в 'char const *' –

+0

@KonradRudolph: сделал это и немного расширил копию/перемещение конструктор предмет. –

0

В этом примере требуется const string & s, чтобы вызвать конструктор из аргумента «HelloWorld». Используемый конструктор - это конструкция преобразования типов.

A string& s не будет работать, поскольку s непосредственно ссылается на строковый объект.

Преобразование типа определяется нечто похожее на

basic_string(const _CharT* __s); 

С ЬурейеГо

typedef basic_string<char> string; 

Так что декларация будет вычисляться

basic_string(const char * __s)  
+0

Это * звучит * неправильный. Либо вы ошибаетесь, либо объяснение неясно. В любом случае 'const' * не * требуется для вызова конструктора копии. –

+0

@ KonradRudolph Это звучало неправильно, потому что это было неправильно, мой мыслящий колпачок был на обратной стороне. –

2

Почему параметр в stringTest должны быть отмечены как const при прохождении ed строка C-Style?

EDIT: Временами должны быть неизменными. См. Комментарий larsmans и ответ, он прав.

Простая причина:

void change(std::string& c) { c = "abc"; } 
change("test"); // what should the code exactly do?? 

Кроме того, что б cstyle строка конструктор выглядеть, и как компилятор знает, чтобы вызвать это Увидав:

Он смотрит std::string для string(char*) конструктор

В случае somethin г как:

std::string s = "HelloWorld"; 

ли cstyle конструктор используется для создания экземпляра временных зОго :: строки, а затем временная строка копируется в «с», используя конструктор копирования строки ?: станда :: строк (Const станда :: строка &);

№ В этом конкретном случае (TYPE variable = SOMETHING), это то же самое, что и написание TYPE variable(SOMETHING);. Таким образом, копирование не используется.

+0

Ваш первый и третий пункты неверны. –

+0

@Конрад, ты уверен, что третий пункт неверен? – nothrow

+0

Да ... см. Ответ larsmans (но и мой комментарий ниже). –

2

Он просто распознает строковый литерал как нечто вроде атрибута char *?

На эту часть оригинального вопроса не ответил так ясно, как хотелось бы. Я полностью поддерживаю (и проголосовал) ответ Йоссариана за остальных.

В принципе, вам нужно понять, что делает компилятор, когда он видит строковый литерал в коде.Этот массив символов (как и любая строка стиля c) действительно хранится в совершенно другом месте, чем код, в котором он входит (в зависимости от архитектуры числовые литералы могут быть сохранены в самом местоположении как часть сборки/двоичная инструкция). Два блока кода здесь «более или менее» эквивалент (игнорировать отсутствие включает или объявления пространства имен):

int main(void) 
{ 
    cout << "Hello!" << endl; 
    return 0; 
} 

Это ближе к тому, что «на самом деле» происходит:

const char HELLO_STR[] = { 'H', 'e', 'l', 'l', 'o', '!', 0 }; 

int main(void) 
{ 
    cout << HELLO_STR << endl; 
    return 0; 
} 

Прости меня, если Я сделал ошибку в init массива или что-то еще, но я думаю, что это выражает то, что я имею в виду, где хранится строковый литерал. Это не в строке, но является невидимой константой для другой части программы, где она определена. Кроме того, некоторые (большинство?) Компиляторов также упорядочивают строковые литералы «вместе», так что, если у вас есть тот же литерал, который используется в 50 местах, он сохраняет только один из них, и все они ссылаются на одну и ту же константу, сохраняя память.

Помните, что всякий раз, когда вы используете строковый литерал, вы используете const char [N], который существует «невидимо» где-то, что неявно преобразуется в const char *.