【问题标题】:Understanding const pointers to const value in C++理解 C++ 中指向 const 值的 const 指针
【发布时间】:2017-12-31 02:29:30
【问题描述】:

我有两个问题。

首先,我对 const 指向 const 值的指针的理解有点问题。我不明白为什么B::insert 有效,而C::insert 会导致编译器错误。我的意思是C中的列表不完全等于C::insert的参数吗?

我的第二个问题是A const * const a,是否也可以写成const A& a

class A
{
    //Do stuff
};

class B 
{
private:
    list<A const *> l;

public:
    void insert(A const * const a)
    {
        l.push_back(a);
    }
};

class C 
{
private:
    list<A const * const> l;

public:
    void insert(A const * const a)
    {
            l.push_back(a);
    }
};

编辑(编译错误):

g++ -Wall  -c  -O2 "sonnensystem.cpp" -std=c++11 (im Verzeichnis: C:\Users\Kenan\Desktop\OPR\cppcode\Konzepte\Kapselung\Architektur\sonnensystem01)
In file included from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32/bits/c++allocator.h:33:0,
             from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/allocator.h:46,
             from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/string:41,
             from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/locale_classes.h:40,
             from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/ios_base.h:41,
             from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ios:42,
             from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ostream:38,
             from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/iostream:39,
             from sonnensystem.cpp:1:
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ext/new_allocator.h: In instantiation of 'struct __gnu_cxx::new_allocator<const A* const>':
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/allocator.h:92:11:   required from 'class std::allocator<const A* const>'
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/stl_list.h:315:9:   required from 'class std::__cxx11::_List_base<const A* const, std::allocator<const A* const> >'
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/stl_list.h:507:11:   required from 'class std::__cxx11::list<const A* const>'
sonnensystem.cpp:28:27:   required from here
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ext/new_allocator.h:93:7: error: 'const _Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::const_reference) const [with _Tp = const A* const; __gnu_cxx::new_allocator<_Tp>::const_pointer = const A* const*; __gnu_cxx::new_allocator<_Tp>::const_reference = const A* const&]' cannot be overloaded
       address(const_reference __x) const _GLIBCXX_NOEXCEPT
       ^
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ext/new_allocator.h:89:7: error: with '_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = const A* const; __gnu_cxx::new_allocator<_Tp>::pointer = const A* const*; __gnu_cxx::new_allocator<_Tp>::reference = const A* const&]'
       address(reference __x) const _GLIBCXX_NOEXCEPT
       ^
Kompilierung fehlgeschlagen.

【问题讨论】:

  • 如果您包含编译器错误将很有用。我的编译器没有错误。
  • @Eljay 查看我的编辑。我也试过这个在线编译器link。也没有在那里工作:/
  • 另见Does C++11 allow vector&lt;const T&gt;?,了解编译器为何抱怨address

标签: c++ list pointers reference constants


【解决方案1】:

在您的声明 A const * const 中,第一个 const 表示 A * 指针指向一个无法更改的值(一个 const 指针)。第二个const 表示该指针的值不能更改,就像const int 不能更改一样。由于list(和其他标准容器)要求其成员是可分配的,因此它们不能是 const 值。

对于第二个问题,A const * constconst A&amp; 相似,但不可互换,因为您使用它们的方式不同。

【讨论】:

  • 谢谢,我现在明白了,但为什么它需要 CopyAssignable?
  • 简短回答:因为语言说它需要。更长的答案:随着容器被复制、创建、调整大小等,元素将被移动和复制,因此容器中的现有值需要可更新(通过复制分配)。
  • 好的,谢谢你的帮助 :) @SornelHaetir 的评论对吗?我试过了,但似乎没有用;/不想在知道他的答案是否正确之前关闭这个线程:D
  • @SaliKe 不,使用emplace_back 不会让它工作。除了创建节点之外,内部还有更多工作要做。
【解决方案2】:

在使用std::list&lt;T&gt; 时,T 的要求之一是它是CopyAssignable。见http://en.cppreference.com/w/cpp/container/list

当您使用const 类型作为参数时,不满足该要求。如果您使用以下命令,您将看到类似的错误,如果不是相同的错误:

std::list<const int> a;
a.push_back(10);

不管怎样,

list<A const * const> l;

不可用。

【讨论】:

    【解决方案3】:

    A const * constA const &amp; 之间唯一真正的区别是更容易检查指针是否无效(您可以将 nul 指针强制转换为 A,然后取消引用以获得空 A 引用,去if(!a)更容易)。

    C::insert 的情况是由于代码试图分配给内部节点值。如果您使用emplace_back 而不是push_back,它可能会起作用。

    【讨论】:

    • 我尝试使用 emplace_back 而不是 push_back,但没有奏效。我认为就像这里的其他人已经说过的那样,通用参数需要是 CopyAssignable。
    猜你喜欢
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多