我有一些代码是在不考虑const正确性的情况下编写的。是否有任何改变这种情况的情况
class X
{
public:
X(X& rhs); // does not modify rhs
...
};
到这个
class X
{
public:
X(const X& rhs);
...
};
会改变现有程序的行为吗?我知道这个更改将允许当前没有编译的代码进行编译,但是如果有任何已经编译的代码会改变它的行为的情况我感兴趣。
类似的问题,改变这个改变有什么好处吗?
class X
{
public:
X(X& rhs); // does not modify rhs
X(const X& rhs);
...
};
答案 0 :(得分:2)
对于复制构造函数,我不这么认为。但请注意,通常,是的,const
的声明可以影响调用哪个方法。想到的唯一例子是数组重载 - 参见例如this question
答案 1 :(得分:1)
实际上,复制构造函数应该是imho,总是将const引用作为其参数。
X(X& rhs) { } // does not modify rhs
这不允许复制const对象,因此以下代码将无法编译。 虽然非const对象可以作为const参数,但另一种方法是不可能的
X const test;
X new_x(test);
我无法想象为什么有人应该排除const对象的副本。
关于您要进行的更改: 复制构造函数是否依赖于任何定义为非const的X成员函数?
这将像魅力一样工作,但允许复制const对象:
class X
{
private:
int a;
public:
X(X &rhs) { a = rhs.value(); }
int& value (void) { return a; }
};
下一个示例将不会编译,因为rhs
是const但value()
不是const。
class X
{
private:
int a;
public:
X(X const &rhs) { a = rhs.value(); }
int& value (void) { return a; }
};
如果你想使你的类const正确,你可能需要检查整个类。 它应该只影响你的类内实现。因为我不知道外部代码应该依赖于类成员函数的“非常量”的情况。 除非在我的示例中由任何公共成员函数返回非const引用。
以下代码段将按预期执行。
class X
{
private:
int a;
public:
X(int const &b) : a(b) { }
X(X const &rhs) { a = rhs.value(); }
int const & value (void) const { return a; }
};
但请注意,这会干扰任何代码,例如:
X test(100);
test.value() = 12;
这可以使用int& value (void) { return a; }
,但无法使用int const & value (void) const { return a; }
。
你当然可以提供安全保障。
答案 2 :(得分:0)
由于您正在更改具有复制构造函数的类,我假设您可以检查复制构造函数代码。如果您可以进行此更改并且复制构造函数不会给出编译器错误,那么您可能很好。需要考虑的一个案例是复制赋值运算符的作用,因为没有保证会在优化代码中调用。因此,还要确保您的复制赋值可以使用const参数。
答案 3 :(得分:0)
djechlin在his answer中提出了一个重点,虽然有点不清楚,所以我会尝试更好地解释。
对象或引用的常量会影响重载决策。例如,如果您有一个基于const
的成员函数重载的对象,则会选择不同的重载:
struct foo {
void do_stuff();
void do_stuff() const;
};
int main() {
foo f;
const foo& fr = f;
f.do_stuff(); // calls non-const version
fr.do_stuff(); // calls const version
}
现在,如果其中一个重载有副作用而另一个没有副作用,那么在更改签名后你会得到不同的行为,因为(或者更确切地说,即使)程序编译得很好