为啥CString变量无法赋值?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥CString变量无法赋值?相关的知识,希望对你有一定的参考价值。
程序停在:CStringData* GetData() const throw()
return( reinterpret_cast< CStringData* >( m_pszData )-1 );
在自己编写的程序中,中断行是:
int CBaseData::IniCurrentFile(CString CurrentFile)
m_CurrentFile = CurrentFile;
//基数据文件列表不为空时,定位当前基数据文件的位置
if ( !vecFileList.empty() )
m_iterCurrent = find(vecFileList.begin(),vecFileList.end(),m_CurrentFile);
//Locates the position of the first occurrence of an element in a range that has a specified value
else
AfxMessageBox(_T("基数据文件列表为空!请首先初始化该列表!"));
return 0;
函数中的第一行,为什么不能赋值给CString变量m_CurrentFile?
int CBaseData::IniCurrentFile(CString CurrentFile)
int CBaseData::IniCurrentFile(const CString& CurrentFile) 参考技术A C没有string变量类型 参考技术B m_CurrentFile是怎么定义的追问
public 类型的变量:CString m_CurrentFile;
追答m_CurrentFile = CurrentFile;
你可以在这行后加个测试代码,比如:AfxMessageBox(m_CurrentFile )
可以跟踪变量的内容
到这就中断了,运行不了下一步啊。
追答到哪一步嘛,对话框没出现?还是出现了字符为空?
其实你没必要这一步,直接使用CurrentFile这个参数,因为你这里的参数传递也是赋值,等于赋值两次
建议在m_CurrentFile = CurrentFile; 这句前面加个测试对话框AfxMessageBox(CurrentFile)
看看参数传递是否有问题
编译出错还是运行出错?
错误提示是什么?
为啥允许我们更改“const”限定变量的值?为啥允许使用指针,但不允许赋值?
【中文标题】为啥允许我们更改“const”限定变量的值?为啥允许使用指针,但不允许赋值?【英文标题】:Why are we allowed to change values of "const" qualified variables?Why pointers are allowed for this,but not assignment?为什么允许我们更改“const”限定变量的值?为什么允许使用指针,但不允许赋值? 【发布时间】:2013-05-08 17:06:15 【问题描述】:考虑以下 2 个程序 prog1 和 prog2。如果我尝试使用指针 ptr
更改 const
限定变量 i
的值,我收到警告(不是错误)"initialization discards qualifiers from pointer target type|"
,但程序仍然运行并显示新值。但是如果我尝试使用赋值语句在第二个程序中更改 i
的值,我得到 错误(非警告)assignment of read-only variable 'i'|
。
以下是由这个前提引起的混淆:
1) 为什么我们可以在任何情况下更改只读const
限定变量的值?这难道不违背使用const
限定符的目的吗?我们试图这样做吗?
2)即使由于某些奇怪的原因我们被允许更改常量的值,为什么要区分使用指针更改只读const
限定变量的值(这是允许的,但有警告)并通过使用赋值操作(这是不允许的并给我们一个错误)?
//prog1
#include <stdio.h>
int main ()
const int i=8;
int *ptr=&i;
*ptr=9;
printf("%d",*ptr); //Prints new value nevertheless
警告:初始化会丢弃来自指针目标类型的限定符|
//prog2
#include <stdio.h>
int main()
const int i=8;
i=10;
printf("%d",i);
错误:赋值只读变量'i'|
编辑 H2CO3
这里我不止一次改变const
限定变量的值。我只得到一个警告,和prog1
一样
//prog3
#include <stdio.h>
int main ()
const int i=8;
int *ptr=&i;
*ptr=9;
*ptr=10;
printf("%d",*ptr); //Prints 10
【问题讨论】:
更正了 2 个错别字。现在确定。 为什么?因为,主要是由于历史原因(以及不良的实践习惯),C 标准已经如此定义或实施。 (在 C++ 中可能有所不同)。 您没有意识到 prog1 没有违规,您在任何时候都不会更改任何 const 内容。您将指针设置为 const'd 指针,然后更改该指针。试试int const* ptr = &i
,然后再试一次。
@Shark Prog1 确实有约束违规。
因为 C 编译器信任程序员,不会尝试修复程序员的错误。
【参考方案1】:
1) 为什么我们可以在任何情况下更改只读
const
限定变量的值?这不是违背了使用const
限定符的目的吗?
试图通过赋值运算符改变一个 const 限定的对象是违反约束的:
约束下的6.5.16:
2 赋值运算符应有一个可修改的左值作为其左操作数。
可修改的左值在 6.3.2.1 (1) 中定义:
可修改的左值是没有数组类型、没有不完整类型、没有 const 限定类型的左值,如果是结构或联合,没有任何具有 const 限定类型的成员(递归地包括所有包含的聚合或联合的任何成员或元素)。
作为约束违规,它需要编译器根据 5.1.1.3 (1) 提供诊断消息:
如果预处理翻译单元或翻译单元包含违反任何语法规则或约束的情况,则符合标准的实现应产生至少一个诊断消息(以实现定义的方式标识),即使该行为也明确指定为未定义或实现定义。在其他情况下不需要生成诊断消息。
但不需要实现来拒绝无效程序,因此诊断消息也可能是警告而不是错误。
但是,通过没有 const 限定类型的左值修改声明为 const
的对象不是违反约束,尽管它会调用未定义的行为,6.7.3 (6):
如果尝试通过使用具有非 const 限定类型的左值来修改使用 const 限定类型定义的对象,则行为未定义。
由于它既不是违反约束也不是无效语法,它甚至不需要发出诊断消息。
如果我们尝试这样做,难道不应该得到错误吗?
如果您尝试通过具有 const 限定类型的左值修改对象,您必须收到诊断消息。
由于严重违反了声明的意图,大多数编译器在这些情况下都会发出错误。
如果您尝试通过具有非 const 限定类型的左值来修改具有 const 限定类型的对象,如
const int i=8;
int *ptr=&i;
*ptr=9;
尝试通过表达式 *ptr = 9
修改 i
会调用未定义的行为,但不是违反约束(或语法错误),因此不需要诊断消息(并且没有给出)。
初始化时发出诊断消息
int *ptr = &i;
因为这又违反了约束,根据 6.5.16.1 (1):
应满足以下条件之一:
左操作数具有原子、合格或非限定算术类型,右操作数具有算术类型; 左操作数具有与右操作数兼容的结构或联合类型的原子、限定或非限定版本; 左操作数具有原子、限定或非限定指针类型,并且(考虑左操作数在左值转换后将具有的类型)两个操作数都是指向兼容类型的限定或非限定版本的指针,和指向的类型to by left 具有所有由 right 指向的类型的限定符; 左操作数具有原子、限定或非限定指针类型,并且(考虑左操作数在左值转换后的类型)一个操作数是指向对象类型的指针,另一个是指向限定或非限定类型的指针void 的非限定版本,左边指向的类型具有右边指向的类型的所有限定符; 左边的操作数是一个原子的、合格的或不合格的指针,右边是一个空指针常量;或 左操作数的类型为 atomic、qualified 或 unqualified _Bool,右操作数是指针。
然而,该诊断通常是一个警告而不是错误,因为人们可能会明确地将 const
扔掉,
int *ptr = (int*)&i;
而不能从i
中丢弃const
。
通过指向非 const 限定对象类型的指针修改对象是有效的,如果指向的对象是可修改。愚蠢的例子:
int i = 8;
const int *cptr = &i; // valid, no problem adding const
int *mptr = (int*)cptr;
*mptr = 9; // no problem, pointee is non-const
2) 即使由于某些奇怪的原因我们被允许更改常量的值,为什么要区分使用指针更改只读 const 限定变量的值(这是允许的,但有警告)和通过使用赋值操作(这是不允许的并且给我们一个错误)?
直接分配给具有 const 限定类型的对象不仅违反约束,而且明显违反所述语义。声明对象const
明确表示“我不希望修改该对象”。
通过指向非 const 限定类型的指针修改对象不是违反约束,只有当指针对象具有 const 限定类型时才会发生未定义的行为。允许将指向 const 限定类型的指针转换为指向相应非 const 限定类型的指针,并且通过该指针修改指针对象可能是有效的,因此您只会收到警告,并且只有在未进行转换的情况下明确的。
在给定的简短示例中,编译器可以检测到指针对象具有 const 限定类型,因此修改会调用未定义的行为,但通常这很难,而且通常无法检测到。因此,编译器甚至不会尝试检测简单的情况,这是不值得的。
【讨论】:
如果您也可以查看以下问题,您会很高兴,也许可以发表评论,因为我不确定它是否值得您回答。 ***.com/questions/16543795/… 我看到 Eric Postpischil 打败了我。他的回答很全面。 谢谢,现在对 Eric Postpischil 新的尊重!!【参考方案2】:为什么我们可以在任何情况下更改只读
const
限定变量的值?
我们不是。我不明白你为什么这么认为,也不知道哪个例子表明了这一点。
为什么要区分使用指针更改只读 const 限定变量的值(这是允许的,但有警告)
再次重申:不允许, 因此发出警告。 (警告要认真对待 - 你似乎没有给他们任何意义......)只是编译器不知道指针指向一些const
-qualified对象(因为它被声明为非常量 T *
)。
至于为什么更改变量有效:
解释 #1:这是未定义的行为(违反约束),所以它可以做任何事情。
解释#2:可能它只是像本地自动变量一样存储在堆栈中,您确实可以更改它。
【讨论】:
我使用了一个指向const
限定变量的指针来多次更改值。难道我们不应该只允许初始化一次吗?等一下。我正在发布一个编辑。检查编辑。
@Rüppell'sVulture int *p = &foo;
p 不是 const-qualified。我也没有看到多次更改它的相关性。赋值不是初始化,是一个或多个赋值。以上是关于为啥CString变量无法赋值?的主要内容,如果未能解决你的问题,请参考以下文章