假设你有一堂课
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 …
这个问题与我的最后一个问题有关.我正在尝试使用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 …
简单的问题.Should I declare any method that can be const a const method?这包括不返回任何成员变量的方法,或返回对成员变量的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)
它似乎工作正常,但实际上这样做是否安全?
我惊讶地发现"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.
这是为什么?看起来像一个问题(它在我的代码中,我找到了它.)
我很困惑为什么下面的代码没有产生任何错误,因为传递给显示的参数是相同的类型,即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]然后它调用第一个显示.它是否意味着字符串现在不再被视为常量?
请考虑下面的代码,特别是观察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) 我偶然发现我可以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>是不通过继承相关的不同类型,为什么这是可能的?
我有以下代码
#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
考虑以下代码:(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
c++ ×9
c ×1
clang++ ×1
clang-tidy ×1
const ×1
constructor ×1
overloading ×1
pointers ×1
qlist ×1
qt ×1
reference ×1
templates ×1
traits ×1