Вопрос

Недавно я написал фрагмент кода, который сделал

SomeClass someObject;
mysqlpp::StoreQueryResult result = someObject.getResult();

где SomeClass::GetResult() выглядит следующим образом:

mysqlpp::StoreQueryResult SomeClass::getResult()
{
mysqlpp::StoreQueryResult res = ...<something>...;
return res;
}

Теперь, используя пример из первого фрагмента кода, когда я скомпилировал и запустил программу, произошел сбой с сигналом прерывания.Затем я изменил первый фрагмент на:

SomeClass someObject;
mysqlpp::StoreQueryResult result(someObject.getResult());

что сработало отлично.Кроме того, просто чтобы попробовать, я снова изменил его на:

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();

который тоже отлично работал.

Теперь я просто не могу понять, почему первый пример провалился, а следующие два увенчались успехом.Как я понимаю, в первом примере конструктор копирования используется для инициализации результата.Но разве это не так и во втором примере?Так почему же второй пример оказался успешным?Третий пример имеет немного больше смысла - поскольку copy const не используется, мы просто присваиваем после построения.

Короче говоря, в чем разница между:

FooClass a = someObject.someMethodReturningFooClassInstance();

и

FooClass a(someObject.someMethodReturningFooClassInstance());?

Огромное спасибо!

Это было полезно?

Решение

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

Вы уверены, что это именно так что вы написали в своем коде?

Другие советы

Строго говоря, в первом случае вызывается конструктор по умолчанию, за которым следует оператор присваивания, а во втором случае используется только конструктор копирования.

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

Вы могли бы просто поместить точку останова (или даже оператор printf) внутрь конструктора копирования, и вы бы точно знали, когда он был вызван, понимаете.ТАК что не могу заменить базовую отладку.;)

Но да, конструктор копирования должен быть вызван в двух первых случаях.В третьем случае вместо этого используется оператор присваивания.

Вы пробовали запустить его в отладчике?Он должен прерваться по сигналу ОТБОЯ.

Ну, на самом деле, первый из них будет выполнять промежуточную копию с помощью operator= , в то время как второй будет выполнять конструкцию прямого копирования.

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

В чистейшей теории конструктор копирования должен вызываться в обоих случаях.Однако существует нечто, называемое оптимизацией возвращаемого значения (RVO), которое компилятору разрешено использовать в этих случаях.Если используется RVO, конструктор копирования вызываться не будет.Возможно, ваш компилятор использует RVO в одном случае, а не в другом?

Редактировать:Это относится только к данному случаю

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top