std ::对象的向量和const-correctness

eis*_*baw 15 c++ vector const-correctness

考虑以下:

class A {
public:
    const int c; // must not be modified!

    A(int _c)
    :   c(_c)
    {
        // Nothing here
    }

    A(const A& copy)
    : c(copy.c)
    {
        // Nothing here
    }    
};



int main(int argc, char *argv[])
{
    A foo(1337);

    vector<A> vec;
    vec.push_back(foo); // <-- compile error!

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

显然,复制构造函数是不够的.我错过了什么?

编辑:Ofc.我无法在operator =()方法中更改this-> c,因此我没有看到如何使用operator =()(尽管std :: vector需要).

GMa*_*ckG 19

我不确定为什么没有人这么说,但正确的答案是放下const或存储A*在向量中(使用适当的智能指针).

您可以通过"复制"调用UB或不执行任何操作(因此不是副本)来为您的类提供可怕的语义,但为什么所有这些都会在UB和坏代码中跳舞?做到这一点你得到了const什么?(提示:没什么.)你的问题是概念性的:如果一个类有一个const成员,那么这个类就是const.从根本上说,不能分配const的对象.

只需使它成为非const 私有,并且不可变地暴露其价值.对于用户来说,这是等效的,不变的.它允许隐式生成的函数正常工作.


Pra*_*rav 15

STL容器元素必须是可复制构造且可分配1(您的类A不是).你需要超载operator =.

1:§23.1The type of objects stored in these components must meet the requirements of CopyConstructible types (20.1.3), and the additional requirements of Assignabletypes


编辑:

免责声明:我不确定以下代码是否100%安全.如果它调用UB或其他什么,请告诉我.

A& operator=(const A& assign)
{
    *const_cast<int*> (&c)= assign.c;
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

编辑2

我认为上面的代码片段调用Undefined Behavior,因为试图抛弃const限定变量的常量调用UB.

  • @eisbaw:抱歉,你不能在重载的`operator =`里面指定`this-> c` [因为它是一个常量]. (4认同)
  • @Prasoon:如果*这被声明为const(例如A const obj(3); obj = A(42);),则它是UB.否则它只是一个[坏主意](http://chat.stackoverflow.com/transcript/message/87298#87298). (2认同)
  • @Roger:是的.`§7.1.5.1/ 4`说`除了可以修改任何声明可变的类成员(7.1.1)之外,任何在其生命周期内修改const对象的尝试(3.8)都会导致未定义的行为.但我们不知道这里有任何`const`对象,所以虽然这是一个坏主意但应该没问题. (2认同)

sje*_*397 7

你错过了一个三大任务之一的赋值运算符(或复制赋值运算符).