const重载和共享指针

时间:2016-07-14 00:33:08

标签: c++ c++11 pointers c++14

试图更好地掌握有关const重载的规则。请考虑以下代码 -

MyClass.h

class MyClass
{
public:
    MyClass();
    ~MyClass();
};

MyClass.cpp

#include "MyClass.h"
MyClass::MyClass() 
{
}
MyClass::~MyClass()
{
}

的main.cpp

#include <iostream>
#include "MyClass.h"
#include <memory>
using namespace std;

/*
void test_function(MyClass& test)
{
    cout << "ref to non const" << endl;
}
*/
void test_function(const MyClass& test)
{
    cout << "ref to const" << endl;
}
/*
void test_shared_ptr( shared_ptr<MyClass>& test)
{
    cout << "ref to non const shared ptr to non const" << endl;
}

void test_shared_ptr ( const shared_ptr<MyClass>& test)
{
    cout << "ref to const shared ptr to non const" << endl;
}
*/
void test_shared_ptr (const shared_ptr<const MyClass>& test)
{
    cout << "ref to const shared ptr to const" << endl;
}

int main()
{
    MyClass non_const_my_class;
    test_function(non_const_my_class);
    const MyClass const_my_class;
    test_function(const_my_class);

    shared_ptr<MyClass> non_const_ptr_to_non_const = make_shared<MyClass>                (MyClass());
    test_shared_ptr(non_const_ptr_to_non_const);

    const shared_ptr<MyClass> const_ptr_to_non_const = make_shared<MyClass>(MyClass());
    test_shared_ptr(const_ptr_to_non_const);

    const shared_ptr< const MyClass> const_ptr_to_const = make_shared< const MyClass>(MyClass());
    test_shared_ptr(const_ptr_to_const);

    int pause;
    cin >> pause;
    return 0;
}

通过注释掉的方法,输出为:

ref to const
ref to const
ref to const shared ptr to const
ref to const shared ptr to const
ref to const shared ptr to const

这个输出是我所期望的,但是我遇到了一些围绕这种类型的const重载的代码的潜在错误。真的只是想对以下陈述进行一些验证:

  1. 将非const数据作为const的引用传递给函数总是可以的,只要该函数不会试图违反其参数的常量。这会导致编译错误。
  2. 它永远不会好,因为它会导致编译错误,将const数据作为对非const的引用传递给函数。这将违反数据的常量。
  3. 作为最后一个问题 -

    在什么情况下您可能需要以下代码?在我上面的测试代码中,将非const数据作为const引用传递给函数是完全没问题的,那么为什么我需要这样做const_cast

    void test_const_cast(const MyClass & test)
    {
        //Do something
    }
    
    void test_const_cast( MyClass & test)
    {
        test_const_cast(const_cast<MyClass const &>(test));
    }
    

3 个答案:

答案 0 :(得分:0)

声明1:关闭对于C ++ 98,比C ++ 11更接近。在C ++ 11中,当涉及标准库时,添加了一个要求,即const成员函数不引入Data Races。见http://channel9.msdn.com/posts/C-and-Beyond-2012-Herb-Sutter-You-dont-know-blank-and-blank。如果一个类型的实例具有引入数据竞争的const成员函数,而非const重载没有,则将一个可变的左值传递给一个引用const的函数是不对的。 即使该函数确实违反了其参数的常量(使用List<AuthorityRole> list = new ArrayList<AuthorityRole>(); list.add(AuthorityRole.ROLE_ADMIN); list.add(AuthorityRole.ROLE_USER); user.setAuthorityRoles(list); )。

声明2: 可以传递const数据作为对非const的引用,提供该函数实际上不会更改其参数引用的对象。这是const_cast<>()的主要用例。

奖金问题:使用const_cast<>() 添加 const的代码主要在重载函数的返回值不为空时有用。例如,标准库为const_cast<>()提供非成员begin()end()函数,使得std::vector<T /* technically more type paraeters here */>的重载,例如返回const vector<int>&,但是需要vector<int>::const_iterator返回vector<int>&的重载。如果您想要vector<int>::iterator而不仅仅是const_iterator,并且不希望将iterator转换为iterator,则可能会这样做。这就是为什么C ++ 17引入const_iterator http://en.cppreference.com/w/cpp/utility/as_const,以便更容易,而不使用可怕的as_const()

答案 1 :(得分:0)

  

将非const数据作为const的引用传递给函数总是可以的,只要该函数不会试图违反其参数的常量。这会导致编译错误。

并非总是如此。 C ++不喜欢传递用常量模板化的类型。请考虑以下代码:

#include <vector>
using std::vector;

void test(const vector<const int> & b) { }

int main() {
  vector<int> a;
  test(a);
}

此处,aint的向量,test接受const的{​​{1}}向量。对const int的约束本质上是一种承诺,它既不会修改test也不会修改其中的元素;直觉上,它根本不应对b施加任何限制。然而代码将无法编译。例如,在clang中,您会收到此错误:

a

删除test_template.cxx:11:3: error: no matching function for call to 'test' test(a); ^~~~ test_template.cxx:5:6: note: candidate function not viable: no known conversion from 'vector<int>' to 'const vector<const int>' for 1st argument void test(const vector<const int> & a) { } ^ 前面的const,实际上它确实编译(至少在clang上)。因此,vector与您总结的方式不同。

答案 2 :(得分:0)

这个问题的答案似乎是它依赖于编译器。可以将非const指针传递给const数据到一个函数,该函数将const数据的const指针作为参数与visual studio编译器一起使用,但不能与gcc一起使用。