LINUX.ORG.RU

C++ копирующий конструктор


0

0

Привет!
Вот есть такой класс:
class TSomeClass
{
public:
TSomeClass(const char * aStr);
TSomeClass & operator= (const char * aStr);
private:
...
};

Помогите понять в чем принципиальное отличие между:

TSomeClass var1("Hello world");
TSomeClass var2 = "Hello world";

Т.е. как отличается создание объектов var1 и var2 ?

Спасибо!

anonymous

в первом случае вызывается параметризованный конструктор, во втором - сначала конструктор по умолчанию, потом operator =.

anonymous
()

не слушай предыдущего анонимуза. Разницы нет.

dilmah ★★★★★
()

Такие вопросы можно и самаому на практике решить :) Отладчиком прогони - разница\не разница будет на лицо ;)

KIV
()
Ответ на: комментарий от eXOR

> По стандарту разницы быть не должно.

Не знаю, как там по стандарту, но в g++ разница есть. Например,
нижеследующий код не собирается с ошибкой (на инициализации с '='):
error: conversion from ‘int’ to non-scalar type ‘A’ requested

===== CUT HERE =====

struct A
{
    A( A const& a ) :
        _m( a._m )
    {}

    explicit A( int m ) :
        _m( m )
    {}

    int _m;
};

int
main()
{
    A a1( 1 );
    A a2 = 2;
    return 0;
}

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

ну так это фича, специально сделанная чтобы запретить конструирование через =, и неявное преобразование.

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

> конструирование через = 
Конструирование может быть осуществленно _только_ через соответствующий конструктор.

aton
()
Ответ на: комментарий от aton

форма записи через =:

Class c = a;

является конструированием. Конечно вызывается конструктор а не оператор =.

Фича explicit, приведенная дедушкой-ваташивой, запрещает такое конструирование.

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

> Фича explicit, приведенная дедушкой-ваташивой, запрещает такое конструирование.

Ты как бы и понимаешь о чем пишешь, но используешь немного не те слова,
это только запутывает остальных. И опять, explicit запрещает
_неявное_преоброзование_, если конструктор
не объявлен как explicit, то он может быть использован в приведенном 
тобой примере + если динамический тип объекта `а' совпадает c `c', 
то _иницализация_копированием_ также может быть выполнена.

aton
()
Ответ на: комментарий от dilmah

> это фича, специально сделанная чтобы запретить конструирование
> через =, и неявное преобразование.

Пример ниже показывает, что конструирование через '=' и есть
преобразование, однако explicit конструктор не запрещает его делать.

===== CUT HERE =====

struct A;
struct B;

struct A
{
    A( A const& o ) :
        _m( o._m )
    {
        cout << "A::A( A const& )" << endl;
    }

    A( int m ) :
        _m( m )
    {
        cout << "A::A( int )" << endl;
    }

    explicit A( B const& );

    int _m;
};

struct B
{
    B( B const& o ) :
        _m( o._m )
    {
        cout << "B::B( B const& )" << endl;
    }

    B( int m ) :
        _m( m )
    {
        cout << "B::B( int )" << endl;
    }

    operator A() const
    {
        cout << "B::operator A()" << endl;
        return A(_m);
    }

    int _m;
};

A::A( B const& o ) :
    _m( o._m )
{
    cout << "A::A( B const& )" << endl;
}

int
main()
{
    A a1( B(1) );
    A a2 = B(2);
    return 0;
}

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от aton

> В этом пример мы имеем implicit conversion, а это уже другой случай.

Инициализация через '=' всегда implicit conversion, просто если конструктор не explicit, то он и используется для преобразования. А вот инициализация через '()' --- это всегда явный вызов конструктора.

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

> Инициализация через '=' всегда implicit conversion
Нет, у тебя в примере реализован соответствующий оператор приведения,
именно поэтому мы получаем implicit conversion.

> просто если конструктор не explicit
об этом я уже писал, смотри выше.

aton
()
Ответ на: комментарий от aton

> у тебя в примере реализован соответствующий оператор приведения, именно поэтому мы получаем implicit conversion.

implicit conversion мы получаем потому, что в инициализации копирования тип инициализатора не совпадает с типом инициализируемого объекта. А оператор приведения позволяет осуществить это приведение, т.к. конструктор A(B const&) объявлен explicit. Если б оператора приведения не было, то implicit conversion никуда бы не делось, но мы получили бы compiler error.

На самом деле, даже если тип инициализатора совпадает с типом инициализируемого объекта, мы можем рассмотривать это как implicit conversion A->A и, таким образом, свести всё к тому, что copy-initialization всегда implicit conversion. Там есть разница только в том, что в copy-initialization _может_быть_ лишний вызов конструктора копирования.

watashiwa_daredeska ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.