2

C++

我想知道一个不是双const指针的指针(例如T const * const)是否可以隐式或显式强制转换,通过某些东西(例如函数)处理,或以其他方式转换,以产生 a T const * const,不使用或在用于初始化之前一个声明为T const * const. 我怎样才能做到这一点?

我认为如果我从 a 开始T*,那么一个const_cast(或两个,以防演员一次只能投射一个const)就足够了,但显然它没有。T const * const代码中的许多变量显示了通过强制转换或从函数返回的不同失败尝试。每个演员都未能返回一个带有尾随的指针const。(我const将左侧*称为前导const,将右侧*称为尾随const。)由于强制转换不成功,我尝试强制const通过直接初始化但未成功。这是在VC11. stack-crooked.com 上的 g++提供了逻辑上等效的控制台输出,尽管名称不同typeid(/*...*/).name().

#include <iostream>
#include <typeinfo>
using namespace std;

int const * const foo()
{
    return nullptr;
}

int main()
{
    int x = 7;

    auto a1 = &x;
    cout << typeid(a1).name() << endl;

    auto a2 = const_cast<int const *>(&x);
    cout << typeid(a2).name() << endl;

    auto a3 = const_cast<int * const>(&x);
    cout << typeid(a3).name() << endl;

    auto a4 = const_cast<int const * const>(&x);
    cout << typeid(a4).name() << endl;

    auto a5 = const_cast<int const * const>(a4);
    cout << typeid(a5).name() << endl;

    auto a6 = (int const * const) &x;
    cout << typeid(a6).name() << endl;

    auto a7 = static_cast<int const * const>(a4);
    cout << typeid(a7).name() << endl;

    auto a8 = reinterpret_cast<int const * const>(a4);
    cout << typeid(a8).name() << endl;

    auto a9 = foo();
    cout << typeid(a9).name() << endl;

    int const * const a10 = &x;
    cout << typeid(a10).name() << endl;
    cout << ( typeid(a10) == typeid(a4) ) << endl;

    auto a12 = a10;
    cout << typeid(a12).name() << endl;
    cout << ( typeid(a12) == typeid(a4) ) << endl;
}

预期结果与实际结果以及问题:

问题编号对应于相同编号的a#变量。

  1. 得到了预期的结果int *
  2. 得到了预期的结果int const *
  3. 期待int* const,但得到了int*。是否const_cast忽略了它的尾随const论点,为什么?由于返回的常量和类型与参数相同,所以演员表运行了吗?
  4. 期待int const * const,但得到了int const*。是否const_cast忽略了它的尾随const论点,为什么?
  5. 鉴于参数已经有一个前导,我想看看是否const_cast<int const * const>会在结果中包含一个尾随。预期。得到。是否忽略了它的尾随论点,为什么?consta4constint const * constint const*const_castconst
  6. 预期int const * const。得到int const*。为什么显式演员仍然会排除尾随const
  7. 预期int const * const。得到int const*。为什么要static_cast排除尾随const
  8. 预期int const * const。得到int const*。为什么要reinterpret_cast排除尾随const
  9. 预期int const * const。得到int const*。为什么对int const * const函数返回的初始化仍然会排除const结果中的尾随?
  10. 预期int const * const。从控制台输出获得int const*,但不是从调试器获得。a10被明确声明为int const * const,那么为什么要typeid().name()排除尾随 const 呢?operator==yield 1,那么为什么它typeid()本身(不仅仅是名称)a10等同于 of a4?VC11 调试器将a10类型列为int const * const. 为什么它与 from typeid()and不同typeid().name()?哪一个是正确的?
  11. 变量名a11省略,因为它看起来像单词“all”。
  12. 我预计a12int const * const因为它被初始化为a10,这是明确声明int const * const的。 operator==产量1typeid()仍然如此int const*。从控制台int const*输出和调试器中获得。为什么它们与预期的结果不同?

所有强制转换、函数返回和初始化是否都仅限于一次强制转换const?领导const是他们唯一可以投入的吗?

4

1 回答 1

3

const_cast确实按照您认为的方式工作。但是,auto并没有做你认为它做的事情。auto与函数模板参数推导类似(实际上,它是根据后者定义的)。现在考虑:

template<typename T>
void f(T x);

f(42);
int const n = 42;
f(n);

两个电话都是 to f<int>(),不是f<const int>()。模板参数推导忽略顶级 const 修饰符。出于同样的原因,在这个例子中

auto a = 42; a = 84;
auto b = n;  b = 84;

变量ab的类型为int, not const int,并且可以修改。

于 2013-10-13T04:17:38.010 回答