Подтвердить что ты не робот

С++ - Назначение нулевой строки

Я изучаю С++ самостоятельно. У меня есть следующий код, но он дает ошибку.

#include <iostream>
#include <string>
using namespace std;


int setvalue(const char * value)
{
    string mValue;
    if(value!=0)
    {
       mValue=value;
    }
    else
    {
       mValue=0;
    }
}

int main ()
{
 const char* value = 0;
 setvalue(value);

 cin.get();
 return 0;
}

Итак, хочу создать функцию, которая принимает указатели char, и я хочу передать указатель на нее. Функция назначает указатель на свою переменную-член. Я намеренно передаю нулевой указатель. Ниже приведена ошибка, которую я получаю:

 D:\CPP\TestCP.cpp In function `int setvalue(const char*)': 

 note C:\Dev-Cpp\include\c++\3.4.2\bits\basic_string.h:422 candidates are: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>] 

 note C:\Dev-Cpp\include\c++\3.4.2\bits\basic_string.h:422                 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>] 

 note C:\Dev-Cpp\include\c++\3.4.2\bits\basic_string.h:422                 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(_CharT) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>] 

он в основном жалуется на строку: mValue = 0;

Почему он жалуется на эту строку? Я не могу назначить null для строки?

4b9b3361

Ответ 1

Я не могу назначить null для строки?

Нет. std::string не является типом указателя; это не может быть сделано "null". Он не может представлять отсутствие значения, которое используется для представления нулевого указателя.

Его можно сделать пустым, назначив ему пустую строку (s = "" или s = std::string()) или очистив ее (s.clear()).

Ответ 2

Вы не можете назначить NULL или 0 объекту С++ std::string, потому что объект не является указателем. Это одно из ключевых отличий от строк в стиле C; строка C-стиля может быть NULL или допустимой строкой, тогда как С++ std::string всегда сохраняет некоторое значение.

Здесь нет легкого решения. Если вы хотите зарезервировать контрольное значение (скажем, пустую строку), тогда вы можете сделать что-то вроде

const std::string NOT_A_STRING = "";

mValue = NOT_A_STRING;

Кроме того, вы можете сохранить указатель на строку, чтобы вы могли установить ее в null:

std::string* mValue = NULL;

if (value) {
    mValue = new std::string(value);
}

Надеюсь, это поможет!

Ответ 3

Литерал 0 имеет тип int, и вы не можете назначить int на std::string. Используйте mValue.clear() или назначьте пустую строку mValue="".

Ответ 4

Можно рассмотреть два метода, которые достигают такого же эффекта для обработки нулевых указателей в строках C-стиля.

Тернарный оператор

void setvalue(const char *value)
{
    std::string mValue = value ? value : "";

}

или утверждение смиренного if

void setvalue(const char *value)
{
    std::string mValue;
    if(value) mValue = value;

}

В обоих случаях value присваивается только mValue, если value не является нулевым указателем. Во всех других случаях (т.е. Когда value равно null), mValue будет содержать пустую строку.

Метод тернарного оператора может быть полезен для предоставления альтернативного строкового литерала по умолчанию при отсутствии значения из value:

std::string mValue = value ? value : "(NULL)";

Ответ 5

Я не буду утверждать, что это хорошая идея (или семантика использования nullptr с вещами, которые не являются указателями), но относительно просто создать класс, который обеспечивал бы " nullable" семантика (см. nullable_string).

Однако это гораздо лучше подходит для С++ 17 std:: optional:

#include <string>
#include <iostream>
#include <optional>

// optional can be used as the return type of a factory that may fail
std::optional<std::string> create(bool b)
{
    if (b)
        return "Godzilla";
    else
        return {};
}

int main()
{
    std::cout << "create(false) returned "
              << create(false).value_or("empty") << std::endl;

    // optional-returning factory functions are usable as conditions of while and if
    if (auto str = create(true))
    {
        std::cout << "create(true) returned " << *str << std::endl;
    }
}

std::optional, как показано в примере, конвертируется в bool, или вы можете использовать метод has_value(), имеет исключения для плохого доступа и т.д. Это дает вам нулевую семантику, которая, кажется, Maria пытался выполнить.

И если вы не хотите ждать совместимости с С++ 17, см. этот ответ о Boost.Optional.

Ответ 6

Случай else невозможен, когда вы создаете объект string, он по умолчанию пуст.

Ответ 7

Многие API-интерфейсы C используют нулевой указатель, чтобы указать "использовать значение по умолчанию", например. mosquittopp. Вот шаблон, который я использую на основе David Cormack:

    mosqpp::tls_set(
        MqttOptions->CAFile.length() > 0 ? MqttOptions->CAFile.c_str() : NULL,
        MqttOptions->CAPath.length() > 0 ? MqttOptions->CAPath.c_str() : NULL,
        MqttOptions->CertFile.length() > 0 ? MqttOptions->CertFile.c_str() : NULL,
        MqttOptions->KeyFile.length() > 0 ? MqttOptions->KeyFile.c_str() : NULL
    );

Это немного громоздко, но позволяет хранить все как std::string вплоть до самого вызова API.

Ответ 8

Компилятор выдает ошибку, потому что при назначении mValue = 0 компилятор находит оператор присваивания = (int) для привязки времени компиляции, но он не присутствует в строковом классе. если мы введем приведение следующего оператора к типу char, например, mValue = (char) 0, то его компиляция завершится успешно, поскольку строковый класс содержит метод operator = (char).