简体   繁体   English

添加const正确性

[英]Adding const correctness

I have some code which has been written without regard for const correctness. 我有一些编写的代码,不考虑const的正确性。 Are there any circumstances in which changing this 是否有任何改变这种情况的情况

class X
{
public:
    X(X& rhs); // does not modify rhs
    ...
};

to this 对此

class X
{
public:
    X(const X& rhs);
    ...
};

would change the behaviour of an existing program? 会改变现有程序的行为吗? I know this change will allow code which doesn't currently compile to compile, but I'm interested if there is any circumstance in which code that already compiles would change it's behaviour. 我知道这个更改将允许当前没有编译的代码进行编译,但是如果有任何已经编译的代码会改变它的行为的情况我感兴趣。

Similar question, is there any merit in making this change instead? 类似的问题,改变这个改变有什么好处吗?

class X
{
public:
    X(X& rhs); // does not modify rhs
    X(const X& rhs);
    ...
};

For copy constructor I don't think so. 对于复制构造函数,我不这么认为。 But note that in general, yes, declaration of const can affect which method is called. 但请注意,通常,是的, const声明可以影响调用哪个方法。 The only example that comes to mind is with array overloading - see eg this question . 想到的唯一例子是数组重载 - 请参阅此问题

In fact a copy constructor should, imho, always take a const reference as its argument. 事实上,复制构造函数应该始终将const引用作为其参数。

X(X& rhs) { } // does not modify rhs

This does not allow to copy const objects and hence the following code will not compile. 这不允许复制const对象,因此以下代码将无法编译。 While non-const objects can serve as const arguments, the other way round is impossible 虽然非const对象可以作为const参数,但另一种方法是不可能的

X const test;
X new_x(test);

I can't imagine why someone should preclude the copy of a const object. 我无法想象为什么有人应该排除const对象的副本。

Concerning the changes you want to make: Does the copy constructor rely on any X member function that is defined non-const? 关于您想要进行的更改:复制构造函数是否依赖于任何定义为非const的X成员函数?

This will work like a charm but permit copying const objects: 这将像魅力一样工作,但允许复制const对象:

class X
{
private:
  int a;
public:
  X(X &rhs) { a = rhs.value(); } 
  int& value (void) { return a; }
};

The next example will not compile since rhs is const but value() is not const. 下一个例子不会编译,因为rhs是const但是value()不是const。

class X
{
private:
  int a;
public:
  X(X const &rhs) { a = rhs.value(); } 
  int& value (void) { return a; }
};

If you want to make your class const correct you'll probably have to examine the whole class. 如果你想使你的类const正确,你可能需要检查整个类。 It should only affect your in-class-implementations. 它应该只影响你的类内实现。 Since I don't know a case where external code should rely on "non-constness" of a class member function. 因为我不知道外部代码应该依赖于类成员函数的“非常量”的情况。 Except when non-const-references are returned by any public member-functions as in my example. 除非在我的示例中由任何公共成员函数返回非const引用。

The following snippet will do as intended. 以下代码段将按预期执行。

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; }
};

But be aware that this will interfere with any code like: 但请注意,这会干扰任何代码,例如:

X test(100);
test.value() = 12;

This would work using int& value (void) { return a; } 这将使用int& value (void) { return a; } int& value (void) { return a; } but fails with int const & value (void) const { return a; } int& value (void) { return a; } ,但无法与int const & value (void) const { return a; } int const & value (void) const { return a; } . int const & value (void) const { return a; } You could of course provide both to be on the safe side. 你当然可以提供安全的一面。

Since you are changing the class that has the copy constructor I am assuming you can inspect the copy constructors code. 由于您正在更改具有复制构造函数的类,我假设您可以检查复制构造函数代码。 If you can make this change and the copy constructor does not give a compiler error you are probably good. 如果您可以进行此更改并且复制构造函数不会给出编译器错误,那么您可能很好。 One conor case to consider is what the copy assignment operator does as there is no assurance which will be called especially in optimized code. 需要考虑的一个案例是复制赋值运算符的作用,因为没有保证会在优化代码中调用。 So also make sure that your copy assignment will work with a const parameter. 因此,还要确保您的复制赋值可以使用const参数。

djechlin is making an important point in his answer , although somewhat unclear, so I will try to explain better. djechlin在他的回答中提出了一个重点,虽然有点不清楚,所以我会尝试更好地解释。

The constness of an object or reference affects overload resolution. 对象或引用的常量会影响重载决策。 For instance, if you have an object with a const based overload of a member function, different overloads will be chosen: 例如,如果您有一个具有基于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
}

Now, if one of the overloads has side-effects the other doesn't, you'd get different behavior after changing the signature, given that (or rather even though ) the program compiles fine. 现在,如果重载之一,具有副作用,其他没有,你改变了签名后,得到不同的行为,考虑到(或者说即使 )程序编译罚款。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM