使用C ++ 17作弊的常数?

问题描述 投票:1回答:1

我发现了一个奇怪的(至少对我来说)行为,在下面的代码中,函数B::Compute() const修改了一个非常量成员。我以为这是不允许的,特别是因为我不打算欺骗constness,例如通过const_cast或类似方式。尽管如此,代码仍会编译(请参见下面的详细信息)。为什么会这样?

#include <vector>
#include <iostream>

class A {
    std::vector<int> v_;
public: 
    A() = default;
    ~A() = default; 
    A& operator=( A const& ) = delete;
    A& operator=( A&& ) = delete;
    A( A const& ) = delete;
    A( A&& ) = delete;

    void AddToA( int const e ) {
        v_.push_back( e );
    }

    void Print() const { 
        for( auto const& v : v_ ) {
            std::cout << v << "\t";
        }
        std::cout << "\n";
    }
};

A InstantiateA() {
    return A();
}

class B {
    A & a_;
public: 
    B() = delete;
    ~B() = default; 
    B& operator=( B const& ) = delete;
    B& operator=( B&& ) = delete;
    B( B const& ) = delete;
    B( B&& ) = delete; 
    B( A & a ) : a_( a ) {}

    void Compute() const {
        a_.AddToA( 1 );
    }
};

B InstantiateB( A & a ) {
    return B( a );
}

int main() {
    A a = InstantiateA(); 
    B b = InstantiateB( a );

    B b2 = B( a );

    b.Compute();
    a.Print();

    b2.Compute();
    a.Print();

    return 0;
}

有关编译的详细信息:我使用提供给定标志的以下编译器进行了测试。对于没有C ++ 17标志的GCC,代码进行not编译。没有其他C ++ 17标志,我没有测试其他编译器。

  • GCC 9.3 -std = c ++ 17
  • ICC 19.0.1 -std = c ++ 17
  • CLANG 10.0.0 -std = c ++ 17
  • MSVC 19.24 / std:c ++ 17example
c++ c++17 const
1个回答
1
投票

a_内部修改b.Compute()引用的对象是合法的,因为您没有在修改a_。创建成员函数const意味着您无法修改存储在成员变量中的值,但是对于引用来说,这已经是不可能的(永远不能更改为引用新对象)。

您在没有C ++ 17标志的情况下无法编译与常量性无关。阅读错误消息;他们告诉您您正在尝试从InstantiateA()函数调用已删除的move / copy构造函数,没有C ++ 17的延迟实现功能是不允许的。

[如果您不愿意将minimal example放在一起,则可能自己会学到这一切。

© www.soinside.com 2019 - 2024. All rights reserved.