Указатель на массив символов и указатель на строку в параметрах - PullRequest
2 голосов
/ 30 января 2010

Я часто вижу следующую структуру, особенно в конструкторах:

class::class(const string &filename)
{
}


class::class(const char * const filename)
{
}

Путем пошаговой отладки я обнаружил, что второй конструктор всегда вызывается, если я передаю жестко закодированную строку.

Любая идея:

1) Почему используется двойная структура?

2) Какая разница в скорости?

Спасибо.

Ответы [ 4 ]

3 голосов
/ 30 января 2010

Требуются два конструктора, потому что вы можете передать NULL в MyClass::MyClass(const std::string &arg). Предоставление второго конструктора спасает вас от глупой аварии.

Например, вы пишете конструктор для вашего класса и заставляете его принимать const std::string &, чтобы вам не нужно было проверять правильность указателей, если вы используете const char*. И везде в вашем коде вы просто используете std::string s. В какой-то момент вы (или другой программист) передаете туда const char*. Вот замечательная часть std::string - у нее есть конструктор, который принимает char*, и это очень хорошо, за исключением того, что std::string a_string(NULL) компилируется без проблем, просто не работает.

Вот тут вам пригодится второй конструктор, как вы показали:

MyClass::MyClass(const char* arg)
    : m_string(arg ? arg : "")
{}

и он создаст действительный std::string объект, если вы передадите ему NULL.

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

РЕДАКТИРОВАТЬ: Только что попробовал std::string a_string(NULL);, прекрасно компилируется, и вот что происходит, когда он запускается на моей машине (OS X + gcc 4.2.1) (я помню, я пытался это на Windows некоторое время назад, результат был очень похоже, если не совсем то же самое):

std::logic_error: basic_string::_S_construct NULL not valid

1 голос
/ 30 января 2010

Это полезно, если реализация имеет дело с const char* s сама по себе, но в основном вызывается std::string пользователями. Они могут вызывать с помощью std::string API, который обычно просто вызывает c_str() и отправляет реализацию const char*. С другой стороны, если у вызывающей стороны уже есть c-строка, нет необходимости создавать временные или ненужные std::string (что может быть дорогостоящим, для более длинных строк - это выделение кучи).

Также я однажды использовал его для разрешения следующего случая:

Мой интерфейс занял std::string, но должен был быть реализован во внешнем модуле, таким образом, двоичные версии STL как модуля, так и модуля вызывающего абонента должны были точно соответствовать , иначе потерпел крах (не очень хорошо для переносимой библиотеки…). Поэтому я изменил фактический интерфейс на использование const char* и добавил std::string перегрузки, которые я объявил inline, чтобы они не экспортировались. Он не сломал существующий код, но решил все проблемы с границами моего модуля.

0 голосов
/ 30 января 2010

Они предлагаются в основном для удобства. Иногда, если вы вызываете функции C, вы получаете указатели char *. Другие, вы получаете строки, так что предложение обоих конструкторов просто удобство для вызывающей стороны. Что касается скорости, оба имеют практически одинаковую скорость, так как они посылают адрес памяти конструктору.

0 голосов
/ 30 января 2010

1) Почему используется двойная структура?

Ссылочная версия строки требуется, если объекты std :: string удобно использовать в качестве параметровm, поскольку не существует неявного преобразования из std :: string в const char const. Версия const char * const является необязательной, поскольку символьные массивы могут быть неявно преобразованы в std :: strings, но это более эффективно, так как не требуется создавать временную std :: string.

2) What is the speed difference?

Вам нужно будет измерить это самостоятельно.

...