Используют ли неявные преобразования типа класса конструктор копирования?

Следующая цитата из моей книги C ++:

Когда мы используем прямую инициализацию, мы просим компилятор использовать обычную функцию сопоставления, чтобы выбрать конструктор, который лучше всего соответствует аргументам
мы предоставляем. Когда мы используем инициализацию копирования, мы просим компилятор скопировать
правый операнд в создаваемый объект, преобразование этого операнда, если
необходимо.

Для меня этот жирный бит вызывает некоторую двусмысленность. Звучит так, будто правый операнд преобразуется в тип класса, а затем, например, используется конструктор копирования;

string s = "hello";

станет…

string s = string("hello");

который использует конструктор копирования. Если это правда, тогда моя тестовая программа;

#include <iostream>
using namespace std;

class A{
public:
A(const A& b): data(b.data) { cout << "The first way" << endl;}
A(const char* c): data(c) { cout << "The second way" << endl;}
string data;

};
int main(){
A first("hello");
A second = "sup";
}

Должно быть продюсирование «Второй путь, Второй путь, Первый путь». Однако вместо этого он печатает «Второй путь, Второй путь». Из этого я бы пришел к выводу, что он использует конструктор const char *, а не конструктор копирования. Я был бы в порядке с этим, кроме как позже это говорит …

Во время инициализации копии компилятору разрешено (но не обязательно) пропустить конструктор копирования / перемещения и создать объект напрямую. То есть компилятору разрешено переписывать

string null_book = "9-999-99999-9";

в

string null_book("9-999-99999-9");

Однако, даже если компилятор пропускает вызов конструктора копирования / перемещения,
Конструктор копирования / перемещения должен существовать и быть доступным (например, не приватным) в этой точке программы.

Я не уверен, почему конструктор копирования даже нуждается в упоминании в этих примерах, не

 string null_book = "9-999-99999-9"

всегда подразумевается, что конструктор const char * все равно используется? На самом деле, для меня не имеет смысла, что конструктор копирования должен быть определен для того, чтобы вышесказанное работало. Но увы, если я поставлю «const A&»конструктор как приватный (остальное публично), тогда моя программа не будет работать. Почему конструктор копирования должен быть определен для неявных преобразований, которые даже не включают его? Какой конструктор делает» string null_book = «9-999-99999-9 «» использовать?

1

Решение

string null_book = "9-999-99999-9"; средства string null_book = string("9-999-99999-9");,

Это использует const char * конструктор для создания временного объекта, а затем null_book является копирование / перемещение построено от временного объекта, а затем временный объект уничтожается.

(Копировать / переместить конструкцию означает, что используется конструктор перемещения, если он доступен; в противном случае конструктор копирования).

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

Компилятор может выбрать использование одного и того же пространства памяти для обоих null_book и временный объект, и пропустить вызовы деструктора временного объекта и null_book конструктор копирования / перемещения.

В вашем случае компилятор действительно решил сделать это, поэтому вы не видите никакого вывода конструктора копирования.

Некоторые компиляторы позволяют отключать копирование с помощью переключателя, например, ССАГПЗ / лязг -fno-elide-constructors,

Подробнее о копировании elision

5

Другие решения