【问题标题】:why cast a smart pointer of const type to smart pointer of type works为什么将 const 类型的智能指针转换为类型的智能指针有效
【发布时间】:2014-07-23 14:29:35
【问题描述】:

知道为什么 a1 =a2 不起作用但 a2=a1 起作用。智能指针模板中必须有一个函数来进行转换?是哪一个?

#include "stdafx.h"
#include<memory>
class TestClass
{
public:
    int a ; 

};
typedef std::shared_ptr<TestClass> TestSP;
typedef std::shared_ptr<const TestClass> TestConstSP;
int _tmain(int argc, _TCHAR* argv[])
{
    TestSP a1 = TestSP();
    TestConstSP a2 = TestConstSP();
    //a1 =a2; //error C2440: '<function-style-cast>' : cannot convert from 'const std::shared_ptr<_Ty>' to 'std::shared_ptr<_Ty>'       
    a2=a1;

    return 0;
}

【问题讨论】:

  • this list 中的第二个(仍标记为 #1)。

标签: c++ templates type-conversion smart-pointers


【解决方案1】:

这是由于使用了const。如果您有 const 指针 'const_ptr' 和非 const 指针 'non_const_ptr',可以这样做:

const_ptr = non_const_ptr; // const_ptr doesn't allow modifying the pointed value, while non_const_ptr does.

但禁止这样做:

non_const_ptr = const_ptr; // const_ptr is `const`. Allowing non_const_ptr to modify the pointed value would'n respect the `const` contract.

以下将起作用:

non_const_ptr = (type *) const_ptr; // You have the right to do that as you explicitely break the contract. 
                                    // The programmer is the boss. This is a bit ugly though.

完全相同的逻辑适用于您的示例。

【讨论】:

    【解决方案2】:

    这是以一种有趣的方式指定的,看起来 MSVC 在这里实现了该标准。分配本身在 §20.8.2.2.3 [util.smartptr.shared.assign]/p1-3:

    中指定
    shared_ptr& operator=(const shared_ptr& r) noexcept;
    template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r);
    

    效果:相当于shared_ptr(r).swap(*this)

    返回*this.

    [注意:临时对象构造和销毁引起的使用计数更新不 可观察到的副作用,因此实现可以通过以下方式满足效果(和隐含的保证) 不同的手段,不创造一个临时的。 &lt;example omitted&gt;]

    相关构造函数在 §20.8.2.2.1 [util.smartptr.shared.const]/p17-19:

    shared_ptr(const shared_ptr& r) noexcept;
    template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
    

    要求:除非Y* 可以隐式转换为T*,否则第二个构造函数不应参与重载决议。

    效果:如果r为空,则构造一个空的shared_ptr对象;否则,构造一个与共享所有权的shared_ptr 对象 r.

    后置条件get() == r.get() &amp;&amp; use_count() == r.use_count().

    由于const TestClass * 不能隐式转换为TestClass *,模板化的构造函数不参与重载决议,呈现shared_ptr(r) 格式错误,因为没有匹配的构造函数。


    编辑:我看到了混乱。 VS2012 在报告编译器错误消息方面设计得很差。编译器发出的完整错误消息是:

    error C2440: '<function-style-cast>' : cannot convert from 'const std::shared_ptr<_Ty>' to 'std::shared_ptr<_Ty>'
          with
          [
              _Ty=const TestClass
          ]
          and
          [
              _Ty=TestClass
          ]
    

    重要的是,错误输出中的两个_Tys 指的是不同的 类型。但是,VS2012 中的错误列表窗口仅将其截断到第一行,并且丢失了该基本信息。您应该查看构建输出以获取完整的错误消息。

    【讨论】:

    • 这解释了 const std::shared_ptr 和 std::shared_ptr 之间的转换,但 std::shared_ptr 与 const std::shared_ptr 相同
    • 不,转换是在shared_ptr&lt;const TestClass&gt;shared_ptr&lt;TestClass&gt; 之间。顶级 const(如const std::shared_ptr&lt;TestClass&gt;)对于转换无关紧要。 VS2013 给了我错误error C2440: '&lt;function-style-cast&gt;' : cannot convert from 'const std::shared_ptr&lt;const TestClass&gt;' to 'std::shared_ptr&lt;TestClass&gt;'
    猜你喜欢
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-23
    • 2018-08-31
    • 2019-09-21
    相关资源
    最近更新 更多