这是一个很好的旧C数组:
int a[10];
Run Code Online (Sandbox Code Playgroud)
这是一个很好的旧C数组,它是const:
const int b[10];
Run Code Online (Sandbox Code Playgroud)
在C++中,似乎有两种方法来定义std::arrays const:
std::array<const int, 10> c;
const std::array<int, 10> d;
Run Code Online (Sandbox Code Playgroud)
这两个定义是否相同?如果是这样,那个惯用的是什么?如果没有,有什么区别?
可能重复:
const和readonly有什么区别?
因此,从我读到的,在C#中,const并且static readonly在程序执行期间都会使值不可更改.
但是,const应该使用不太可能改变的数量(例如,pi,地球半径,每加仑的窝数等).
另一方面,static readonly应该使用当前不变但可能/将来会改变的值(例如软件版本,算法中的乘数等).
我做对了吗?
这段代码出了什么问题?我收到此错误:"分配给'....'的表达式必须是常量"
public const string ConnectionString = System.IO.File.ReadAllText(@"D:\connection.ini");
Run Code Online (Sandbox Code Playgroud) 使用带有指针的const可以通过使用有问题的指针解除引用而使得指针不可修改.但为什么我也不能修改指针没有直接指向的东西?
例如:
int a = 3;
const int* ptr = &a;
*ptr = 5;
Run Code Online (Sandbox Code Playgroud)
不会编译.但为什么呢
*(ptr + 2) = 5;
Run Code Online (Sandbox Code Playgroud)
还没编译?我没有改变指针指向的内容.
所以我们不得不说使用带有指针的const这样不仅使得指针指向的内容不可修改(通过解引用指针)而且还有其他任何东西,我们使用指针获取地址吗?
我知道在示例中我试图访问未分配的内存,但这只是为了讨论.
我有一个外部库,我无法修改.该库声明了一个模板函数,该函数由于某种原因返回const非引用对象:
template<class C>
const C foo();
Run Code Online (Sandbox Code Playgroud)
我有另一个外部库,我无法修改.该库声明了一个不可复制的类,并且只有非const对象的移动构造函数:
struct bar {
bar();
bar(const bar&)=delete;
bar(bar&&);
};
Run Code Online (Sandbox Code Playgroud)
现在我需要使用foo<bar>.一个简单的用法:
bar buz() {
return foo<bar>();
}
Run Code Online (Sandbox Code Playgroud)
失败了
Run Code Online (Sandbox Code Playgroud)main.cpp: In function 'bar buz()': main.cpp:13:21: error: use of deleted function 'bar::bar(const bar&)' return foo<bar>(); ^ main.cpp:8:5: note: declared here bar(const bar&)=delete; ^~~
这是有道理的,并没有简单的解决方法使代码编译.
但是,如果我添加一些更复杂的解决方法:
bar buz() {
return const_cast<bar&&>(std::move(foo<bar>()));
}
Run Code Online (Sandbox Code Playgroud)
它编译并且整个代码按预期工作(不仅是上面的简化示例,而且我的真实代码也是如此).
但是,它是安全的,还是我遇到了一些未定义的行为?有没有更好的解决方法?
我已阅读并理解有关返回的问题const从功能(1,2),以及常见的答案似乎是返回const对象在现代C++气馁,但我的问题是不是这件事,但我如何能解决该情况当外部库返回const对象时.
在C++中,可以声明堆栈分配的对象const:
const Class object;
Run Code Online (Sandbox Code Playgroud)
之后尝试在这样的对象上调用非const方法是未定义的行为:
const_cast<Class*>( &object )->NonConstMethod(); //UB
Run Code Online (Sandbox Code Playgroud)
堆分配的对象可以const具有相同的后果吗?我的意思是有可能是以下几点:
const Class* object = new Class();
const_cast<Class*>( object )->NonConstMethod(); // can this be UB?
Run Code Online (Sandbox Code Playgroud)
还是未定义的行为?
例如:
constexpr int g() { return 30; }
constexpr int f()
{
// Can we omit const?
const int x = g();
const int y = 10;
return x + y;
}
Run Code Online (Sandbox Code Playgroud)
有没有必要在constexpr函数中声明局部变量const?
局部变量的constexpr函数不等于没有const局部变量的函数吗?const
换句话说,constexpr函数是否强加(暗示)const它的局部变量?
我在理解此代码段中的行为时遇到了一些麻烦:
unsigned int i = 2;
const int &r = i;
std::cout << r << "\n";
i = 100;
std::cout << r << "\n";
Run Code Online (Sandbox Code Playgroud)
第一个print语句按预期给出2,但是当我更改引用变量的值时,它不会反映在引用中.第二个印刷声明也给出2,但我认为它应该给100?
如果我将变量i变为类型int而不是unsigned int,它就像我期望的那样工作.这里发生了什么?
为什么C++允许编译以下代码?
std::unordered_map<std::string, int> m;
// ...
for (const std::pair<std::string, int>& p: m)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
根据Scott Meyers的Effective Modern C++(p.40-41):
[...] a的关键部分
std::unordered_map是const,所以std::pair哈希表中的类型(它是什么std::unordered_map)不是std::pair<std::string, int>,它是std::pair <const std::string, int>.但这不是p上面循环中为变量声明的类型.因此,编译器将努力找到一种方法将std::pair<const std::string, int>对象(即哈希表中的内容)转换为std::pair<std::string, int>对象(声明的类型p).它们将p通过复制每个对象来创建一个想要绑定的类型的临时对象m,然后将引用p绑定到该临时对象.在每次循环迭代结束时,临时对象将被销毁.如果你编写了这个循环,你可能会对这种行为感到惊讶,因为你几乎肯定打算简单地将引用绑定p到每个元素中m.
允许这种隐式转换有什么好处?是否有一些常见的用例,开发人员期望/更喜欢这种隐式转换(而不是获得编译器错误)?
想象一下以下声明:
void foo(){
const std::array<int, 80000> arr = {/* a lot of different values*/};
//do stuff
}
Run Code Online (Sandbox Code Playgroud)
第二个:
void foo(){
static const std::array<int, 80000> arr = {/* a lot of different values*/};
//do stuff
}
Run Code Online (Sandbox Code Playgroud)
如果有的话,这两者之间可能存在哪些性能差异?这些解决方案是否有任何危险?