Нет пути. Ссылка на указатель, доступ к которому осуществляется через *
или ->
, всегда является lvalue. Он встроен в язык, и типы интеллектуальных указателей стандартной библиотеки соответствуют этому базовому языку.
shared_ptr<container<type>>::operator->
в конечном итоге возвращает container<type>*
, к которому применяется оператор стрелки. Оператор стрелки эквивалентен выполнению (*ptr).get()
. Таким образом, вы всегда будете применять get()
к тому, что язык считает lvalue.
И это значение. Тот факт, что общий указатель является временным, не меняет того факта, что он указывает на занятую память, на lvalue.
Они не абсолютно идентичны. Первое называют "прямой инициализацией", в то время как второе называют "инициализацией копии".
Теперь, Стандарт составляет два правила. Первое для прямой инициализации и для инициализации копии, где инициализатор имеет тип инициализированного объекта. Второе правило для инициализации копии в других случаях.
Так, с той точки зрения оба названы в одном - первом - правило. В случае, где у Вас есть инициализация копии с тем же типом, компилятору позволяют игнорировать копию, таким образом, это может создать временный файл, Вы создаете непосредственно в инициализированный объект. Таким образом, можно закончить очень хорошо с тем же сгенерированным кодом. Но конструктор копии, даже если копия игнорируется (оптимизированный), должен все еще быть доступным. Т.е. если у Вас есть частный конструктор копии, тот код недопустим, если код, в котором это появляется, не имеет никакого доступа к нему.
Второе называют инициализацией копии, потому что, если тип инициализатора имеет другой тип, временный объект создается в попытке неявно преобразовать правую сторону в левую сторону:
myclass c = 3;
Компилятор создает временный объект типа myclass затем, когда существует конструктор, который берет интервал. Затем это инициализирует объект с тем временным файлом. Также в этом случае созданный временный файл может быть создан непосредственно в инициализированном объекте. Можно выполнить эти шаги путем печати сообщений в конструкторах / деструкторы класса и использования опции -fno-elide-constructors
для GCC. Это не пытается игнорировать копии затем.
На заметке на полях тот код выше не имеет никакого отношения к оператору присваивания. В обоих случаях, что происходит, инициализация.
Во втором временный объект создается сначала и затем копируется в объект x использование конструктора копии myClass. Следовательно оба не то же.
Второй может или не может призвать к дополнительному myclass
объектная конструкция, если копия elision не реализована Вашим компилятором. Однако большинство конструкторов, имейте копию elision включенный по умолчанию даже без любого переключателя оптимизации.
Отметьте инициализацию, в то время как конструкция никогда не называет оператор присваивания.
Всегда, имейте в виду:
присвоение: уже существующий объект получает новое значение
инициализация: новый объект получает значение в данный момент, он рождается.
Я записал, что следующие, чтобы попытаться проиллюстрировать понимают то, что продолжается:
#include <iostream>
using namespace std;
class myClass
{
public:
myClass(int x)
{
this -> x = x;
cout << "int constructor called with value x = " << x << endl;
}
myClass(const myClass& mc)
{
cout << "copy constructor called with value = " << mc.x << endl;
x = mc.x;
}
myClass & operator = (const myClass & that)
{
cout << "assignment called" << endl;
if(this != &that)
{
x = that.x;
}
return *this;
}
private:
int x;
};
int main()
{
myClass x(3);
myClass y = myClass(3);
}
Когда я компилирую и выполняю этот код, я получаю следующий вывод:
$ ./a.out
int constructor called with value x = 3
int constructor called with value x = 3
Это, казалось бы, указало бы, что нет никакого различия между двумя вызовами, выполненными в основной функции, но это было бы неправильно. Как litb указанный, конструктор копии должен быть доступен для этого кода для работы, даже при том, что он игнорируется в этом случае. Чтобы доказать что, просто переместите конструктора копии в код выше к частному разделу определения класса. Необходимо видеть следующую ошибку:
$ g++ myClass.cpp
myClass.cpp: In function ‘int main()’:
myClass.cpp:27: error: ‘myClass::myClass(const myClass&)’ is private
myClass.cpp:37: error: within this context
Также обратите внимание, что оператор присваивания никогда не называют.