Явный конструктор копирования

Я расширил std::string, чтобы удовлетворить мои потребности в написании пользовательских функций для сборки в классе строк с именем CustomString

Я определил конструкторы:

    class CustomString : public std::string {
    public:
        explicit CustomString(void);
        explicit CustomString(const std::string& str);
        explicit CustomString(const CustomString& customString);
        //assignment operator
        CustomString& operator=(const CustomString& customString);
    ... };

В третьем конструкторе (конструкторе копирования) и операторе присваивания, определение которого:

CustomString::CustomString(const CustomString& customString):
    std::string(static_cast<std::string>(customString)) 
{}
CustomString& CustomString::operator=(const CustomString& customString){
    this->assign(static_cast<std::string>(customString));
    return *this;
}

Во-первых, так как это "явный"; означает, что для присвоения другому объекту CustomString требуется явное приведение; он жалуется на назначение.

CustomString s = CustomString("test");

Я не уверен, где именно приведение в порядок необходимо явно.

Код работает нормально, если конструктор копирования не является явным, но я хотел бы знать и реализовать явное определение вместо "угадывания правильного приведения".

3 ответа

Решение

Явный конструктор копирования означает, что конструктор копирования не будет вызываться неявно, что и происходит в выражении:

CustomString s = CustomString("test");

Это выражение буквально означает: создать временный CustomString используя конструктор, который принимает const char*, Неявно вызвать конструктор копирования CustomString скопировать из этого временного в s,

Теперь, если код был правильным (т.е. если конструктор копирования не был явным), компилятор избегал бы создания временной и удалял копию, создавая s непосредственно со строковым литералом. Но компилятор должен по-прежнему проверять, что конструкция может быть выполнена и не работает там.

Вы можете вызвать конструктор копирования явно:

CustomString s( CustomString("test") );

Но я бы порекомендовал вам вообще избежать временного и просто создать s с const char*:

CustomString s( "test" );

Что именно так и сделает компилятор...

Получение из std:: string небезопасно, так как std:: string не имеет виртуального деструктора. Что касается вашего вопроса - ваши конструкторы копирования не должны быть явными, чтобы разрешить такое использование как:

CustomString s = "test";

Также я понятия не имею, почему вы хотели бы объявить конструктор копирования явным, так как он не нужен. Явный конструктор копирования будет работать, только если вы объявите свой объект CustomString как:

CustomString s(CustomString("test"));

Кажется, текущий gcc не будет вызывать конструктор копирования, протестированный в gcc 8.2(MinGW.org GCC-8.2.0-5), и будет использовать для прямого вызова конструктора для X1

      #include <iostream>

using std::cout;
using std::endl;


class X1 {
public:

    X1() {
        cout<< "invoke constructor" << endl;
    }; 

    explicit X1(const X1 &obj)  { 
        cout << "invoke copy constructor" << endl;
    };

    X1(X1&& obj)  {
        cout << "invoke move constructor" << endl;
    };

    X1& operator=(const X1 &obj) {
        cout << "invoke value assign constructor " << endl;
        if(this == &obj) {
            return *this;
        }
        return *this;
    };

    X1& operator=(const X1 && obj) {
        cout << "invoke move value assign constructor " << endl;
        if(this == &obj) {
            return *this;
        }
        return *this;

    };

    ~X1() {
        cout << "invoke deconstruct" << endl;
    };



};

int main() {
//    X1 l1(1);
//    X1 l3(2);
    X1 l4 = X1();

    return 0;
}
Другие вопросы по тегам