标签: const-correctness

如何处理const对象中非const引用成员的初始化?

假设你有一堂课

    class C 
    {
      int * i;

      public:

         C(int * v):i(v) {};

         void method() const;  //this method does not change i
         void method();        //this method changes i
    }
Run Code Online (Sandbox Code Playgroud)

现在您可能想要定义此类的const实例

    const int * k = whatever;
    const C c1(k); //this will fail
Run Code Online (Sandbox Code Playgroud)

但是这会因为非const int C的构造函数C(int*v)而失败

所以你定义了一个const int构造函数

    C(const int * v):i(v) {}; //this will fail also
Run Code Online (Sandbox Code Playgroud)

但是这也会失败,因为C的成员"int*i"是非const的.

在这种情况下该怎么办?使用可变吗?铸件?准备const版本的课程?

编辑:经过与Pavel的讨论(下图),我对此问题进行了一些调查.对我来说,C++的作用并不正确.指针目标应该是严格类型,这意味着您不能执行以下操作:

int i;
const int * ptr;
ptr = & i;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,语言语法将const承诺不改变指针的目标.另外int * const ptr是承诺不改变指针值本身.因此,您有两个可以应用const的地方.那么你可能希望你的类为指针建模(为什么不).在这里,事情正在崩溃.C++语法提供了const方法,它们能够保证不会自己更改字段的值,但是没有语法指出你的方法不会改变你的类指针的目标.

解决方法是定义两个类const_C,C …

c++ constructor const-correctness

6
推荐指数
2
解决办法
1965
查看次数

在C++中使用traits

这个问题与我的最后一个问题有关.我正在尝试使用traits<T> 和解决问题 traits<T*>.请考虑以下代码.

template<typename T>
struct traits
{
    typedef const T& const_reference;
};

template<typename T>
struct traits<T*>
{
    typedef const T const_reference;
};

template<typename T>
class test
{
public:   
    typedef typename traits<T>::const_reference const_reference;
    test() {}   
    const_reference value() const {
        return f;
    }
private:
    T f;
};

int main()
{
    const test<foo*> t;
    const foo* f = t.value(); // error here. cannot convert ‘const foo’ to ‘const foo*’ in initialization
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以它看起来像编译器不考虑指针性状专业化,并采取返回类型value()const …

c++ templates const-correctness traits

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

我应该声明任何可以是const const方法的方法

简单的问题.Should I declare any method that can be const a const method?这包括不返回任何成员变量的方法,或返回对成员变量的const引用.有没有理由不这样做(除了显而易见的原因,编译器会指出这些原因)?

c++ const-correctness

6
推荐指数
3
解决办法
254
查看次数

Qt - QList const正确性

A QList<T *>不容易纠正.考虑这个功能

void f(QList<T *> list)
{
    list[0]->constFunction();
}
Run Code Online (Sandbox Code Playgroud)

我可以改变f到

void f(QList<const T *> list)
Run Code Online (Sandbox Code Playgroud)

但后来我不能这样做

f(QList<T *>());    //Compile error
Run Code Online (Sandbox Code Playgroud)

再也没有了,因为编译器不能隐含地强制转换QList<T *>QList<const T *>.但是,我可以明确地重新解释QList,如下所示:

template <typename T> inline QList<const T *> &constList(const QList<T *> &list)
{
    return (QList<const T *> &)list;
}
Run Code Online (Sandbox Code Playgroud)

这使我能够使用constList模板函数将任何内容QList<T *>转换为a QList<const T *>,如

f(constList(QList<T *>()));
Run Code Online (Sandbox Code Playgroud)

它似乎工作正常,但实际上这样做是否安全?

c++ qt const-correctness qlist

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

从const方法对成员调用nonconst方法

我惊讶地发现"const"中的这个"漏洞":

#include <stdio.h>

class A
{
  int r ;
public:
  A():r(0){}

  void nonconst()
  {
    puts( "I am in ur nonconst method" ) ;
    r++;
  }
} ;

class B
{
  A a ;
  A* aPtr ;

public:
  B(){ aPtr = new A() ; }

  void go() const
  {
    //a.nonconst() ;      // illegal
    aPtr->nonconst() ;  //legal
  }
} ;

int main()
{
  B b ;
  b.go() ;
}
Run Code Online (Sandbox Code Playgroud)

因此,基本上从const方法B::go(),如果指针引用了类型的对象,则可以调用非const成员函数(恰当地命名nonconst())A.

这是为什么?看起来像一个问题(它在我的代码中,我找到了它.)

c++ pointers const const-correctness

6
推荐指数
2
解决办法
350
查看次数

const函数重载

我很困惑为什么下面的代码没有产生任何错误,因为传递给显示的参数是相同的类型,即char.const真的有所不同吗?

#include<iostream>

using namespace std;

void display(char *p)
{
    cout<<p;
}
void display(const char *p)
{
    cout<<p;
}

int main()
{
    display("Hello");
    display("World");
}
Run Code Online (Sandbox Code Playgroud)

编辑 根据答案,永远不会调用第一个显示,这是正确的,输出也是如此.

但是假设我这样做:

int main()
{
    char *p="Hello";
    display(p);//now first display is called.
    display("World");
}
Run Code Online (Sandbox Code Playgroud)

编译器提供了一个warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]然后它调用第一个显示.它是否意味着字符串现在不再被视为常量?

c++ overloading const-correctness

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

理解“顶层的‘const’,这可能会降低代码的可读性,而不会提高 const 的正确性”

请考虑下面的代码,特别是观察get_length返回const size_t.

#include <stdio.h>

const size_t get_length(void)
{
    return 123;
}

void foo(void)
{
    size_t length = get_length();
    length++;
    
    printf("Length #1 is %zu\n", length);
}

void bar(void)
{
    // Still 123 because length was copied from get_length
    // (copy ellision notwithstanding, which is not the point here)
    size_t length = get_length();
    
    printf("Length #2 is %zu\n", length);
}

int main(void) {
    foo();
    bar();
}
Run Code Online (Sandbox Code Playgroud)

输出:

Length #1 is 124
Length #2 is 123
Run Code Online (Sandbox Code Playgroud)

我从 clang-tidy 收到以下警告:

Clang-Tidy: …
Run Code Online (Sandbox Code Playgroud)

c const-correctness clang-tidy

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

为什么我可以有一个 constpair&lt;const T, T&gt; 对pair&lt;T, T&gt; 的引用?

我偶然发现我可以const std::pair<const int, int>&参考std::pair<int,int>

#include <utility>
int main()
{
    std::pair<int, int> p{1,2};
    const std::pair<const int, int>& ref_ok{p}; // why does this work?
    std::pair<const int, int>& ref_invalid{p}; // then why does this not work?
}
Run Code Online (Sandbox Code Playgroud)

考虑到const std::pair<const int, int>std::pair<int, int>是不通过继承相关的不同类型,为什么这是可能的?

c++ reference const-correctness

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

为参考参数和优化更改创建临时对象

我有以下代码

#include <iostream>

void foo(const int* const &i_p) {
    std::cout << &i_p << std::endl;
}

int main () {

    int i = 10;
    int* i_p = &i;
    std::cout << &i_p << std::endl;
    foo(i_p);
}
Run Code Online (Sandbox Code Playgroud)

x86-64 clang 9.0.0输出上是

Program returned: 0
0x7ffc43de63f8
0x7ffc43de6400
Run Code Online (Sandbox Code Playgroud)

x86-64 clang 10.0.0 而在编译器资源管理器链接上,输出变为

Program returned: 0
0x7ffc9da01ef0
0x7ffc9da01ef0
Run Code Online (Sandbox Code Playgroud)

这里进行了什么优化来提供相同的地址?我相信应该实现一个临时对象,因为我们无法将低级const指针绑定到低级non-const

c++ const-correctness language-lawyer clang++ reference-binding

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

可以将 const T*&amp;&amp; 绑定到 T* 类型的 xvalue 吗?

考虑以下代码:(https://godbolt.org/z/8W699x6q6

int* p;
const int*&& r = static_cast<int*&&>(p);
Run Code Online (Sandbox Code Playgroud)

注意:const int*&&是指向 的指针的右值引用const int

Clang 编译它,并r绑定到一个临时对象:

p: .quad   0
r: .quad   _ZGR1r_ // r is a reference to a temporary object, otherwise this would be p
Run Code Online (Sandbox Code Playgroud)

GCC 拒绝此代码:

<source>:2:18: error: binding reference of type 'const int*&&' to 'int*' discards qualifiers
    2 | const int *&&r = static_cast<int*&&>(p);
      |                  ^~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

就我个人而言,我认为 GCC 正确地实现了CWG 2352[dcl.init.ref] p4的更改,但我不确定我的解释是否正确。这里哪个编译器是正确的?


注意:本问题中的示例受到CWG 2018中提到的最后一行代码的启发。

注意:如果允许绑定const int*&& …

c++ const-correctness language-lawyer temporary-objects reference-binding

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