我已将参数设为const&函数,因为我希望能够向其传递“字符串文字”。但是我想知道是否可以修改引用,像这样:
void addObjectToDictionary(int* obj, const std::string& name)
{
for (int = 0; i < 10; ++i)
{
if (/*Name already exists in dictionary*/)
name = "object" + std::to_string(rand());
else { /*Add obj to dictionary*/; return; }
}
}
int main()
{
addObjectToDictionary(new int(6), "somename");
)
我想知道是否没有定义掉std :: string引用上的const。该网站上的另一个答案是:
const_cast仅在投射最初非常量的变量时才是安全的。例如,如果您有一个采用const char *参数的函数,并且传入了可修改的char *,则将const_cast该参数返回给char *并进行修改是安全的。
但是,我想知道调用函数时创建的临时std :: string对象是否被视为const。
答案 0 :(得分:3)
我已将参数设为const&函数,因为我希望能够向其传递“字符串文字”。
如果您有兴趣,可以像这样使用字符串文字的确切类型...
"string literal"
...是const char[15]
。碰巧的是,std::string
的构造函数采用const char*
,const char[15]
会自动衰减为const std::string&
,因此字符串文字会绑定到(const char[15]) --> decay --> (const char*) --> bind --> std::string::string( const char* )
参数。
std::string
这将创建一个临时std::string
,其中包含字符串文字的副本。然后,您的函数将那个临时const std::string&
当作const
。 原始临时文件实际上不是原始临时文件是否为const
const
显然在标准中是一厢情愿的,但是 {根据另一个答案,在C ++ 17中为{1}}。
但是我想知道是否可以修改参考
我想知道是否没有定义掉std :: string引用上的const。
如果要修改临时目录,则不需要const_cast
。该语言为您提供了一种以非const
方式绑定到临时对象的方式:rvalue
引用。
// this is a const lvalue reference
// it binds to temporaries
void addObjectToDictionary(int* obj, const std::string& name);
// this is an rvalue reference
// it also binds to temporaries, and will bind to temporaries instead of a
// const lvalue reference if both overloads exist
void addObjectToDictionary(int* obj, std::string&& name);
您陈述的问题的答案...
根据另一个答案,对于C ++ 17,但是,我想知道调用函数时创建的临时std :: string对象是否被视为const。
...是否,临时不是显然是。 const
但是,y 您也不应通过const
左值引用来临时使用const
并将其抛弃,因为该签名也实际上绑定到了const
对象。相反,您可以使用const
引用参数以非{rvalue
的方式绑定到临时目录。
作为奖励,如果您想直接绑定到字符串文字,则可以执行以下操作:
// this templates functions that bind to the exact type of any string literal
template<std::size_t N>
void addObjectToDictionary(int* obj, const char ( &name )[N] );
此模板生成绑定到任意长度的字符串文字的确切类型的函数。这可能有点过分。
注释中有建议按值取字符串(std::string
,无参考)。这也是将字符串“下沉”到函数中的一种完全有效的方法。
// this will bind to string literals without creating a temporary
void addObjectToDictionary(int* obj, std::string name);
那么,这里发生的情况有些不同。将字符串文字传递给const std::string&
参数时,您会获得对临时const
的{{1}}引用。将字符串文字传递给普通的旧std::string
值时,曾经是临时值的现在是您自己想要的std::string
值对象,该对象由字符串文字构造而成。
答案 1 :(得分:2)
首先,您可以随时使用const_cast
。只是,如果您尝试修改实际上是const
的对象,则编译器无法在编译时捕获该行为,则行为是不确定的。使用const_cast
只会增加您这样做的风险。
关于您的情况临时变量是否为const
的问题:答案似乎是“是”。关于针对每个C ++标准版本的引用初始化的措辞,已经有许多缺陷报告,因此,我将在这里讨论C ++ 17的措辞。标准中的相关规定是[dcl.init.ref] /5.2.2.1:
如果
T1
或T2
是类类型,并且T1
与T2
没有引用相关,则使用复制初始化规则考虑用户定义的转换通过用户定义的转换(类型为“ cv1T1
”的对象)(11.6、16.3.1.4、16.3.1.5);如果相应的非引用副本初始化格式不正确,则程序格式不正确。如非引用副本初始化所述,对转换函数的调用结果将用于直接初始化引用。对于这种直接初始化,不考虑用户定义的转换。
对于std::string
prvalue是否经过cv限定尚不清楚,但是在任何情况下prvalue都将用于初始化引用,该引用受p5.2.1的约束,这要求prvalue继承要初始化的引用的cv限定词。因此很明显,创建的临时对象的类型为const std::string
。
所以,在:
const std::string& name = "somename";
您会得到一个const
临时工,但是当您这样做时
std::string&& name = "somename";
您会得到一个非const
临时字符。临时人员的简历合格与参考人的简历相符。