标签: const-correctness

什么时候成员函数应该有const限定符,什么时候不应该?

大约六年前,一位名叫Harri Porten的软件工程师写了这篇文章,问了一个问题,"成员函数什么时候应该有const限定符?什么时候不应该?" 我发现这是我能找到的关于这个问题的最好的写作,我最近一直在努力解决这个问题,而且我认为在大多数关于const正确性的讨论中,这个问题都没有得到很好的解释.由于当时不存在像SO这样强大的软件信息共享站点,我想在这里重新提出这个问题.

c++ const-correctness

7
推荐指数
1
解决办法
2271
查看次数

C++避免了const和非const访问的代码重复

我有一个类应该为每个成员变量调用一个访问者方法.像这样的东西:

class A{
    int a, b, c;

public:
    void accept(Visitor &visitor){
        visitor.visit(a);
        visitor.visit(b);
        visitor.visit(c);
    }
};
Run Code Online (Sandbox Code Playgroud)

如何void accept() const在没有代码重复的情况下使用相同的代码获取方法?

重复的显而易见的解决方案是添加一个方法:

void accept(Visitor &visitor) const {
    visitor.visit(a);
    visitor.visit(b);
    visitor.visit(c);
}
Run Code Online (Sandbox Code Playgroud)

该方法具有我想要的含义,但我想避免代码重复.拥有这两种方法的原因是能够通过"阅读"访问者读取变量并accept很好地使用该方法const.然后非const accept将可用于"写入/更新"访问者.

c++ const-correctness visitor-pattern

7
推荐指数
1
解决办法
1386
查看次数

const Class& 和 Class const& 之间有什么区别吗?

这些表达之间有什么区别:

const Class&
Class const&
Run Code Online (Sandbox Code Playgroud)

例如,当这些是函数的参数时?

reference const-correctness

7
推荐指数
1
解决办法
1089
查看次数

结构初始化中的const正确性

我现在正在玩C++和const-correctness.假设您具有以下结构

template <typename T>
struct important_structure {
    public:
    T* data;
    int a;
    important_structure(const T& el, int a);
    void change();
};

template <typename T>
void important_structure<T>::change() {
    //alter data field in some way
}

template <typename T>
important_structure <T>::important_structure(const T& el, int a) : data(&el), a(a) //error line {
};


int main() {
    important_structure<int>* s = new important_structure<int>{5, 3};
}
Run Code Online (Sandbox Code Playgroud)

编译时std=c++11,编译器返回以下错误:

从'const int*'到'int*'的无效转换

现在,我知道这是不安全投下const int*int*.问题是我有一个数据结构,我不想把字段data作为常量.

但是,我不想删除const构造函数中的限定符,因为我认为它为未来的开发人员提供了信息:它明确表示el不会被函数修改.仍然data可以通过其中的一些其他功能来修改该字段important_structure …

c++ const-correctness

7
推荐指数
1
解决办法
350
查看次数

如何在具有非常量指针键的映射中通过常量指针键查找

以下 C++ 代码无法编译,因为它将非常量指针传递给需要 const 指针的find()函数。

#include <map>

std::map<int*, double> mymap;

double myfind(const int * mykey)
{
    return mymap.find(mykey)->second;
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在不改变地图类型或使变量mykey非常量的情况下使查找工作?毕竟函数find()不会修改指向的对象,它只是比较指针。

c++ stl const-correctness const-cast const-pointer

7
推荐指数
1
解决办法
1154
查看次数

msvc std::lower_bound 需要 const 运算符*

我得到了

Error   C2678   binary '*': no operator found which takes a left-hand operand of type 'const _InIt' (or there is no acceptable conversion)
Run Code Online (Sandbox Code Playgroud)

它是由 MSVC (2022, V17.1) 标头中的代码抛出的<algorithm>

Error   C2678   binary '*': no operator found which takes a left-hand operand of type 'const _InIt' (or there is no acceptable conversion)
Run Code Online (Sandbox Code Playgroud)

const由于上面一行的原因,第二行抛出了错误。

我传入的迭代器是“平面文件”上的自定义 LegacyRandomAccessIterator,它operator*看起来像这样:

template <class _FwdIt, class _Ty, class _Pr>
_NODISCARD _CONSTEXPR20 _FwdIt lower_bound(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val, _Pr _Pred) {

... …
Run Code Online (Sandbox Code Playgroud)

c++ const-correctness

7
推荐指数
1
解决办法
221
查看次数

std::unique_ptr 中运算符 * 的常量正确性

为什么 std::unique_ptr 的 'operator*' 成员函数可以标记为 const ( https://en.cppreference.com/w/cpp/memory/unique_ptr/operator *) 而像 'front()'、 'back( std::vector 中的 )'、'operator[]' 等未标记为 const?两者都返回对其管理的资源的非常量引用。

核心问题是我无法理解第一部分,即为什么我们能够将“operator*”标记为 const,即当该函数中的“*this”指针是 const 时,返回类型如何为“T&”指针(由于函数被标记为 const)?

c++ const-correctness unique-ptr

7
推荐指数
1
解决办法
394
查看次数

Const正确性:const char const*const GetName const(// stuff);

标记为作业,因为这是一个关于期中考试的问题,我写道,我不明白答案.我被要求在以下声明中解释每个const的目的:

const char const * const GetName() const { return m_name; };
Run Code Online (Sandbox Code Playgroud)

那么,每个这些争论的解释是什么?

c++ const-correctness

6
推荐指数
1
解决办法
4374
查看次数

为什么在抛弃指向该对象的指针而不是UB后写入非const对象?

根据C++标准,const如果对象const本身不是,那么抛弃指针并写入对象是可以的.这样:

 const Type* object = new Type();
 const_cast<Type*>( object )->Modify();
Run Code Online (Sandbox Code Playgroud)

没关系,但这个:

 const Type object;
 const_cast<Type*>( &object )->Modify();
Run Code Online (Sandbox Code Playgroud)

是UB.

原因在于,当对象本身是const允许编译器优化对它的访问时,例如,不执行重复读取,因为重复读取对于不改变的对象没有意义.

问题是编译器如何知道实际上是哪些对象const?例如,我有一个功能:

void function( const Type* object )
{
    const_cast<Type*>( object )->Modify();
}
Run Code Online (Sandbox Code Playgroud)

并将其编译为静态库,编译器不知道它将被调用的对象.

现在调用代码可以这样做:

Type* object = new Type();
function( object );
Run Code Online (Sandbox Code Playgroud)

它会很好,或者它可以做到这一点:

const Type object;
function( &object );
Run Code Online (Sandbox Code Playgroud)

它将是未定义的行为.

编译器应该如何遵守这些要求?如果不使后者工作,它应该如何使前者工作?

c++ const const-correctness const-cast undefined-behavior

6
推荐指数
1
解决办法
694
查看次数

boost :: optional不让我重新分配const值类型

在我看来应该有四种变体 boost::optional

  • optional<Foo> =>持有一个可变的Foo,可以在初始化后重新分配

  • optional<Foo const> const =>持有一个const Foo,初始化后无法重新分配

  • optional<Foo> const =>(应该?)保持一个可变的Foo,但在初始化后不能重新分配

  • optional<Foo const> =>(应该?)持有一个const Foo,可以在初始化后重新分配

前2个案例按预期工作.但是对optional<Foo> constconst Foo 的解引用,并且optional<Foo const>在初始化之后不允许重新分配(如本问题所述).

const值类型的重新分配是我遇到的具体内容,错误是:

/usr/include/boost/optional/optional.hpp:486:错误:使 'const的富' 为 '这个' 的参数 '富&富::运算符=(const的富&)' 丢弃限定符[-fpermissive]

它发生在这里:

void assign_value(argument_type val,is_not_reference_tag) { get_impl() = val; }
Run Code Online (Sandbox Code Playgroud)

构造之后,实现使用赋值运算符作为参数化可选的类型.它显然不希望左手操作数是一个const值.但是为什么不能将非const可选项重置为新的const值,例如在这种情况下:

optional<Foo const> theFoo (maybeGetFoo());
while (someCondition) {

    // do some work involving calling some methods on theFoo
    // ...but they should only be const ones

    theFoo = maybeGetFoo();
}
Run Code Online (Sandbox Code Playgroud)

一些问题:

  • 我是否正确,希望这在概念上很好,而且无法做到这只是实施中的侥幸?

  • 如果我不编辑boost源,那么在上面的循环中实现逻辑的干净方法是什么,而不是完全废弃boost :: optional?

  • 如果这确实有意义并且我要编辑boost …

c++ boost const-correctness assignment-operator boost-optional

6
推荐指数
1
解决办法
3856
查看次数