我在代码中占有一席之地
const myType & myVar = someMethod();
问题在于:
someMethod()返回const myType
我需要稍后更改myVar,方法是在对象处于无效状态时指定默认值。所以我需要让myVar
成为非const。
我认为我需要让myVar
成为非参考,对吧?例如。 myType myVar
这种const-to-nonconst的C ++“正确”方法是什么?静态演员?词汇演员?还有别的吗?
我可以访问boost的词汇演员,所以我不介意这个选项,但我更喜欢非 boost 解决方案,如果它最终我不允许使用 boost 。
谢谢!
答案 0 :(得分:9)
你可能不需要任何演员。如果您可以复制T
,那么您还可以复制T const
,排除病理情况。 T const
的副本不必是T const
本身。
myType myVar = someMethod(); // Creates a non-const copy that you may change.
答案 1 :(得分:5)
我不会使用const_cast解决方案,复制对象可能无效。相反,为什么不有条件地分配给另一个const引用呢?如果myVar有效,请指定。如果不是,请指定默认值。然后下面的代码可以使用这个新的const引用。一种方法是使用条件表达式:
const myType& myOtherVar = (myVar.isValid() ? myVar : defaultVar);
另一种方法是编写一个带有const引用(myVar)的函数,并返回myVar或defaultVar,具体取决于myVar的有效性,并将其返回值赋给myOtherVar。
第三种方法是使用const指针,将其指向myVar的地址或默认对象的地址。
答案 2 :(得分:1)
const_cast<type without const>()
但是,someMethod()
真的会返回const myType
吗?如果是这样,你正在引用一个临时的 - 它将被销毁,你的参考将是坏的。将myVar
更改为非ref(因此它会复制) - 在这种情况下无需将其声明为const。或者,如果someMethod()
返回引用,请使用const_cast
(如果必须)(但您正在更改someMethod
认为不会更改的内容。)
答案 3 :(得分:1)
没有“C ++”方式(不仅是这种方式,还包括任何方式)。
糟糕的方法是使用const_cast
,但行为将是未定义的(读取:不要这样做)。
您应该做的是复制对象,然后修改副本。它是处理不可变对象的唯一正确的方法。
答案 4 :(得分:0)
尝试以下
myType& mutableMyVar = const_cast<myType&>(myVar);
一般来说,删除const是一个坏主意。调用方法返回一个对它认为将被视为const的变量的引用。如果通过删除const并修改变量来违反此假设,则可以将任一对象置于有效状态。
在您的特定情况下,这可能是合法的,但一般来说这是应该避免的事情
答案 5 :(得分:0)
您可以使用复制构造函数或某些赋值运算符从const对象创建对象,然后对其进行修改。
但我认为你最好先看看为什么函数首先返回const类型。将它声明为const是有原因的。如果您非常确定这是您想要的,那么您可以像这样const_cast远离const:
T obj1 = const_cast<T&> (obj);
答案 6 :(得分:0)
执行此const-to-nonconst的C ++“正确”方法是什么?静态演员?词汇演员?还有别的吗?
没有C ++方式。由于某种原因,该类的作者决定您不能通过此方法修改实例。
如果您是作者,则可以使其返回非const引用。但是那些仍然是可疑的,除非这个类真的没有业务隐藏它(例如,矢量不会隐藏它为你拥有的,只是隐藏如何它为你拿东西。)
一种更好的方法(取决于它的全部内容)也可能不会暴露成员进行外部操作,而是提供一种方法来为您执行此操作。例如:
class BadPosition
{
int x, y;
public:
int& get_x() { return x; }
int& get_y() { return x; }
//...
};
BadPosition p;
p.get_x() += 1;
p.get_y() += -1;
class BetterPosition
{
int x, y;
public:
void move(int x_inc, int y_inc) { x += x_inc; y += y_inc; }
//...
};
BetterPosition p;
p.move(1, -1);
如果您以后需要将该类置于有效状态,那么可以考虑使其构造函数执行此操作。如果你不能这样做,至少提供一个Init()方法,以免使这样一个复杂的类完全依赖外部操作成可用的东西。
当然可能有其他方式不需要强制转换,例如,您可以创建副本,修改它,然后使用修改后的副本将整个实例替换为另一个(假设这足以构建它):< / p>
X x;
...
Y y = x.get();
y.modify();
x = X(y);
编辑:那么该类按值返回?在这种情况下,应该没有办法修改类中的实例,因为你得到的只是一个副本。您可以使用const引用引用它,但即使您从该引用中删除constness,您仍然引用临时引用。
我上面的回复假设它返回了一个const引用,因为这似乎是一个更明智的事情(我没有看到人们经常返回 const 值,尽管可能有强烈的人推荐它。)