Re[4]: warning C4239, auto_ptr, VS2005
От: K13 http://akvis.com
Дата: 20.01.10 09:43
Оценка: 14 (1) +1
C>>Так нельзя делать, это обман. Человек, копирующий объект посредством конструктора с параметром-константой, ожидает, что оригинал останется неизменённым.

R>Лично я с этим согласен. Но именно так себя ведет std::auto_ptr.


только у std::auto_ptr конструктор принимает обычую ссылку, а не константную.
Явно говоря, что с параметром может произойти что-то нехорошее.
Re[2]: warning C4239, auto_ptr, VS2005
От: Centaur Россия  
Дата: 20.01.10 09:26
Оценка: 7 (1)
Здравствуйте, rg45, Вы писали:

R>Второй способ — сделать так, чтоб коструктор копии принимал константную ссылку, а член _Myptr объявить с ключевым словом mutable:

R>class auto_ptr1
R>{
R>public:
R>    auto_ptr1(int *_Ptr = 0) : _Myptr(_Ptr) { }
R>    auto_ptr1(const auto_ptr1& _Right) : _Myptr(_Right.release()) { }

R>    int *release();
R>private:
R>    mutable int* _Myptr;
R>};

R>auto_ptr1 Func()
R>{
R>    return auto_ptr1(new int);
R>}


Так нельзя делать, это обман. Человек, копирующий объект посредством конструктора с параметром-константой, ожидает, что оригинал останется неизменённым.
Re: warning C4239, auto_ptr, VS2005
От: crable США  
Дата: 20.01.10 10:00
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Объясните инвалиду детства на голову, почему компилируя следующий код с помощью VS2005 я получаю предупреждение C4239?

А>По какой причине такое преобразование запрещено стандартом? Где тут грабли?
А>И как добиться желаемого результат без предупреждений?

Подсмотреть как это сделано в std::auto_ptr


struct auto_ptr_ref
{
  int *_Myptr;
};

class auto_ptr
{
public:
  ...

  auto_ptr(auto_ptr_ref ref)
    : _Myptr(ref._Myptr)
  {
  }

  operator auto_ptr_ref()
  {
    auto_ptr_ref ref = { _Myptr };
    _Myptr = 0;
    return ref;
  }

  ...

private:
  int *_Myptr;
};
The last good thing written in C was Franz Schubert's Symphony No. 9.
warning C4239, auto_ptr, VS2005
От: Аноним  
Дата: 20.01.10 08:49
Оценка:
Объясните инвалиду детства на голову, почему компилируя следующий код с помощью VS2005 я получаю предупреждение C4239?
По какой причине такое преобразование запрещено стандартом? Где тут грабли?
И как добиться желаемого результат без предупреждений?
class auto_ptr1
{
public:
    auto_ptr1(int *_Ptr = 0)
        : _Myptr(_Ptr)
    {
    }

    auto_ptr1(auto_ptr1& _Right)
        : _Myptr(_Right.release())
    {}

    int *release()
    {
        int *_Tmp = _Myptr;
        _Myptr = 0;
        return (_Tmp);
    }
private:
    int* _Myptr;
};

auto_ptr1 Func()
{
    return auto_ptr1(new int);
}
c4239 auto_ptr vs2005
Re: warning C4239, auto_ptr, VS2005
От: Were  
Дата: 20.01.10 09:12
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Объясните инвалиду детства на голову, почему компилируя следующий код с помощью VS2005 я получаю предупреждение C4239?

А>По какой причине такое преобразование запрещено стандартом? Где тут грабли?
А>И как добиться желаемого результат без предупреждений?

Можно решить так
auto_ptr1 Func()
{
    return new int;
}


или так
auto_ptr1 Func()
{
    auto_ptr1 ptr(new int);
    return ptr;
}

Связано с тем, что auto_ptr1 копируется при выходе из функции. Но его конструктор копирования принимает неконстантную ссылку. А временный объект не может быть передан по неконстантой ссылке.
Re: warning C4239, auto_ptr, VS2005
От: rg45 СССР  
Дата: 20.01.10 09:20
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Объясните инвалиду детства на голову, почему компилируя следующий код с помощью VS2005 я получаю предупреждение C4239?

А>По какой причине такое преобразование запрещено стандартом? Где тут грабли?
А>И как добиться желаемого результат без предупреждений?

А другие компиляторы, Comeau, например, вообще ошибку выдают. А дело в том, что конструкция:
return auto_ptr1(new int);

использует коструктор копии для копирования временного объекта auto_ptr1(new int) в результат функции. Но конструктор копии твоего класса принимает неконстантную ссылку. А, как известно, на временные объекты по стандарту можно получать только константные ссылки.

Теперь как исправить.

Способ первый, лобовой:
auto_ptr1 Func()
{
  auto_ptr1 p(new int);
  return p;
}


Второй способ — сделать так, чтоб коструктор копии принимал константную ссылку, а член _Myptr объявить с ключевым словом mutable:
class auto_ptr1
{
public:
    auto_ptr1(int *_Ptr = 0) : _Myptr(_Ptr) { }
    auto_ptr1(const auto_ptr1& _Right) : _Myptr(_Right.release()) { }

    int *release();
private:
    mutable int* _Myptr;
};

auto_ptr1 Func()
{
    return auto_ptr1(new int);
}
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: warning C4239, auto_ptr, VS2005
От: rg45 СССР  
Дата: 20.01.10 09:24
Оценка:
Здравствуйте, Were, Вы писали:

W>Здравствуйте, Аноним, Вы писали:


А>>Объясните инвалиду детства на голову, почему компилируя следующий код с помощью VS2005 я получаю предупреждение C4239?

А>>По какой причине такое преобразование запрещено стандартом? Где тут грабли?
А>>И как добиться желаемого результат без предупреждений?

W>Можно решить так

W>
W>auto_ptr1 Func()
W>{
W>    return new int;
W>}
W>


Вообще-то, в классах умных указателей, во избежание сюрпризов, конструкторы по указателям обычно объявляют explicit. Поэтому так лучше не делать.
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: warning C4239, auto_ptr, VS2005
От: Vladimir35 http://www.mobile-mir.com/ru/
Дата: 20.01.10 09:27
Оценка:
R>Второй способ — сделать так, чтоб коструктор копии принимал константную ссылку, а член _Myptr объявить с ключевым словом mutable:
Думаете, поможет?
Re[3]: warning C4239, auto_ptr, VS2005
От: rg45 СССР  
Дата: 20.01.10 09:31
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Так нельзя делать, это обман. Человек, копирующий объект посредством конструктора с параметром-константой, ожидает, что оригинал останется неизменённым.


Лично я с этим согласен. Но именно так себя ведет std::auto_ptr.
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: warning C4239, auto_ptr, VS2005
От: rg45 СССР  
Дата: 20.01.10 09:45
Оценка:
Здравствуйте, Vladimir35, Вы писали:

R>>Второй способ — сделать так, чтоб коструктор копии принимал константную ссылку, а член _Myptr объявить с ключевым словом mutable:

V>Думаете, поможет?

Поможет, только чуть-чуть еще надо допилить:
class auto_ptr1
{
public:
  explicit auto_ptr1(int *_Ptr = 0) : _Myptr(_Ptr) { }
  auto_ptr1(const auto_ptr1& _Right) : _Myptr(_Right._release()) { }
  int* release() { return _release(); }

private:
  int* _release() const
  {
    int *_Tmp = _Myptr;
    _Myptr = 0;
    return (_Tmp);
  }

  mutable int* _Myptr;
};

auto_ptr1 Func()
{
  return auto_ptr1(new int);
}
--
Справедливость выше закона. А человечность выше справедливости.
Re[5]: warning C4239, auto_ptr, VS2005
От: rg45 СССР  
Дата: 20.01.10 09:51
Оценка:
Здравствуйте, K13, Вы писали:

C>>>Так нельзя делать, это обман. Человек, копирующий объект посредством конструктора с параметром-константой, ожидает, что оригинал останется неизменённым.


R>>Лично я с этим согласен. Но именно так себя ведет std::auto_ptr.


K13>только у std::auto_ptr конструктор принимает обычую ссылку, а не константную.

K13>Явно говоря, что с параметром может произойти что-то нехорошее.

Да, действительно. Наврал я, получается. Честно говоря, std::auto_ptr я недолюбливаю и практически не использую.
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: warning C4239, auto_ptr, VS2005
От: Николай Ивченков  
Дата: 20.01.10 20:46
Оценка:
crable:

C>Подсмотреть как это сделано в std::auto_ptr


Кстати, копирующий конструктор можно вообще сделать закрытым. Тот, кто захочет забрать владение у объекта, обозначаемого lvalue, может продемонстрировать своё намерение явно посредством вызова функции move:

template <class T>
    class auto_ptr
{
public:
    auto_ptr(T * = 0);
    auto_ptr(auto_ptr_ref ref);
    operator auto_ptr_ref<T>();
    auto_ptr_ref<T> move();
    ....

private: // prohibited:
    auto_ptr(auto_ptr &); // undefined
private:
    ....
};

auto_ptr<int> f()
{
    auto_ptr<int> ptr1(new int);
    auto_ptr<int> ptr2 = ptr1.move(); // OK
    auto_ptr<int> ptr3 = ptr1;        // error
    return auto_ptr<int>(new int);    // OK
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.