我很困惑。我看到当代码是这样的
void fun(const char **p) { }
int main(int argc, char **argv)
{
fun(argv);
getchar();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它显示error: invalid conversion from 'char**' to 'const char**'
但是当代码像这样
void test(const char *p) { }
int main()
{
char *c = new char('a');
test(c);
}
Run Code Online (Sandbox Code Playgroud)
然后就没有编译错误了。两个代码有什么区别?
为什么第二段代码可以将变量传递给常参数的函数?
我有一个函数(请不要关心通过引用返回临时.这只是一个解释问题的例子),
const foo<const int>& get_const()
{
foo<int> f;
return f;
}
Run Code Online (Sandbox Code Playgroud)
这显然不会编译.我正在寻找一种方法,以确保调用方不会改变T的foo.我该如何确保?
我见过类似的行为boost::shared_ptr.shared_ptr<T>可转换为const shared_ptr<const T>.我无法弄清楚它是如何做到这一点的.
任何帮助都会很棒.
const正确让我有些困惑.
您使用什么经验法则来决定什么时候应该是const?
例如,考虑这个例子
class MyClass
{
string ToString(); // this one?
const string& ToString(); // or this?
const string& ToString() const; // or this?
char* ToString(); // What about this?
const char* ToString(); // or this?
const char* ToString() const; // or this?
const char const* ToString(); // Is this legal?
const char const* ToString() const; // how about this?
char const* ToString(); // or even this?
};
Run Code Online (Sandbox Code Playgroud)
Const可能会让人感到困惑.
所有这些ToString方法之间有什么区别?
如果我理解正确,第一个返回一个新的字符串对象,如果需要可以修改.第二个返回一个常量引用,也许它应该是字符串const和ToString().第三个可能是废话,因为引用总是不变的是正确的吗?
以为我会把旧的char*版本放在那里进行比较,因为我有返回对象指针的方法,我不确定它们是否应该是const.
我想我只是想了解const正确性的局限性和好处,以及如何预先确定某些东西是否应该是const以及如何正确地应用const,因为将const放在不同的位置会改变含义.
编辑:另外,我如何处理'...丢弃限定符'.这究竟意味着什么?
我制作了一个openGL相机类,它使用延迟评估通过getter函数提供最终投影或模型 - 视图 - 投影矩阵.用户在实例的整个生命周期(FOV,位置等)中提供各种相机参数,但不是每次更改参数时都重新计算投影矩阵和/或MVP矩阵,而是设置"已更改"标志(即旧的缓存矩阵现在无效).只要用户随后请求更新的最终矩阵,就会重新计算,结果缓存,并返回const引用.
一切都听起来不错,直到我打电话给我:
const QMatrix4x4& oE_GLCamera::getModelViewProjection() const;
Run Code Online (Sandbox Code Playgroud)
来自const oE_GLCamera实例的函数...我在我的应用程序中使用const引用来从CAD视口中提取相机数据而不更改相机,但是如果它们无效,我的getter函数会对成员变量执行惰性求值 - 因此会破坏const正确性.
是否有语言功能或设计范例我不知道如何帮助解决这个问题?或者懒惰的评估从根本上与const正确性不兼容?我知道const_cast <>,我自己从未使用过它,但读了一些关于它的内容,可以归结为:如果你使用它,你已经在某个地方出错了.还是会成为我的救世主?
Cam,任何建议都会得到很好的接受
我最近开始尝试在我的代码中强制执行const正确性.在函数定义中,我提供一个指向类的常量对象的常量指针LorentzM:
void AnalysisObject::SetOwnedPointer(const int maptotree_In, const LorentzM* const momentum_In){
owned_pp4_original.reset(momentum_In);
maptotree=maptotree_In;
}
Run Code Online (Sandbox Code Playgroud)
这里owned_pp4_original是
shared_ptr<LorentzM> owned_pp4_original;
Run Code Online (Sandbox Code Playgroud)
我这样做,因为这个函数,SetOwnedPointer,永远LorentzM* momentum_In不应该更改它也不应该更改它指向的对象,因此它是常量指针.
然而,一个shared_ptr创建到momentum_In指向的对象,我也想用这个shared_ptr的改变对象以后:
void ChangeLorentzM(const double px, const double py, const double pz, const double E){
owned_pp4_original->SetPxPyPzE(px,py,pz,E); //THIS CHANGES THE OBJECT
}
Run Code Online (Sandbox Code Playgroud)
所以,一方面,能够做到:
owned_pp4_original.reset(momentum_In);
Run Code Online (Sandbox Code Playgroud)
owned_pp4_original 应该是一个 shared_ptr<const LorentzM>
但是,我无法通过它改变对象.
这张照片有什么问题?
非常感谢.
在许多现代语言中,const应该使用正确性来阐明接口和意图,并为编译器提供一些优化的机会.在D中,存在真正不可变数据的很酷的特征.应该如何const和immutable使用?我有点想,更喜欢const作为函数参数和immutable局部变量的限定符似乎是编写代码的好方法,但是只要你想要一个带有引用或指针的结构,如数据成员(私有或非私有),不可变的变量,你不能这样做.
struct S {
private int[] data;
}
void main() {
immutable s = new S; // won't work, since members aren't immutable
}
Run Code Online (Sandbox Code Playgroud)
因此,struct如果我使用不可变的话,更改a的实现会破坏我的代码.我是否更喜欢const局部变量并仅在必要时使用不可变?指导方针是什么?
所以我有这个代码:
class ConstTest {
public:
explicit ConstTest(char* name) {}
};
int main() {
ConstTest t("blarghgh");
}
Run Code Online (Sandbox Code Playgroud)
它显然是编译,即使我认为它不应该.由于C++中的字符串文字具有类型const char[],而ConstTest构造函数需要const-less char*- not const char*.并且const通过C++隐式地执行指向非常量指针的指针.
那么,我哪里错了?为什么要编译?我可以合法地修改构造函数中的解除引用指针吗?!
请原谅我这个相当模糊的标题,但它确实有点说出来.这就是我的意思
class A
{
void DoSomething(); // non-const
}
Class B
{
public:
B(A& a) : _a(a) { }
// const function
void DoSomethingElse() const
{
// Is there a way to disallow this?
_a.DoSomething();
}
void DoEvenMore()
{
// Should be OK
_a.DoSomething();
}
private:
// Can't make it const A& because it needs
// be non-const for non-const functions
A& _a; // A reference
}
Run Code Online (Sandbox Code Playgroud)
那么有什么方法可以防止B::DoSomethingElse()打电话A::DoSomething()?
但是,B::DoEventMore()哪个不const应该继续通话.
我正在使用Visual C++ 2013. …
经过多年盲目地接受std::vector<T>::operator[] const返回的事实const_reference,但是,鉴于const如何为智能指针工作,我现在开始想知道为什么它和其他STL容器都是这样设计的.似乎a的"constness" const std::vector既适用于向量及其元素,而对于智能指针,"constness"仅适用于指针而不适用于它所指向的元素.
为了澄清,似乎应该有一个类似矢量的容器,const这意味着用户不能改变容器的大小,但容器中的元素是可变的.我的主要问题是:是否有某些东西可以阻止这种类型的容器"const正确"?
似乎通过添加一个额外的间接层(例如std::vector<std::unique_ptr<T>> const)来实现这一点有一些hackish变通方法,但我正在寻找一些在维护方面不那么尴尬的东西.
顺便说一句,如果在STL容器之前将智能指针合并到语言中,那么const访问器是否仍然按照它们今天的方式定义?
这是原型execv:
int execv(const char *path, char *const argv[]);
Run Code Online (Sandbox Code Playgroud)
我可以传递一个const char指针数组作为第二个参数吗?
此示例程序在USE_CAST未设置时发出警告:
#include <unistd.h>
int main(int argc, char *argv[])
{
if (argc > 0) {
const char *exe_name = "/bin/echo", *message = "You ran";
const char *exe_args[] = { exe_name, message, argv[0], NULL };
#ifdef USE_CAST
execv("/bin/echo", (char **) exe_args);
#else
execv("/bin/echo", exe_args);
#endif
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在编译时,gcc说,"如果我不使用强制转换,则从不兼容的指针类型传递'execv'的参数2".
从POSIX文档为execv(中途理由部分),它看起来像第二个参数是char *const为了向后兼容数组:
包含有关
argv[]和envp[]成为常量的语句,以明确未来的语言绑定编写者,这些对象是完全不变的.......遗憾的是,第四列无法使用......
"第四栏"所指的地方const char* …
c++ ×8
const ×2
boost ×1
c ×1
c++11 ×1
constants ×1
d ×1
exec ×1
immutability ×1
pointers ×1
posix ×1
shared-ptr ×1
stl ×1
templates ×1
visual-c++ ×1