2010-08-06 96 views
2

我通常在C/C++代码中使用C类型铸造。我的问题是,在转换类型中添加“const”关键字对结果意味着什么?用“const”关键字C类型铸造

例如,我能想起来的几个场景:

const my_struct *func1() 
{ 
    my_struct *my_ptr = new my_struct; 

    // modify member variables 

    return (const my_struct *)my_ptr; 
    // return my_instance; 
} 

在这其中,功能构建一个结构的新实例,并铸造一个常量指针,因此调用者就不能进一步修改其内部状态,但删除它。是否需要“推荐”或者根本不需要“const”转换,因为任何return语句都可以工作。

在这一个中,my_basemy_derive的基类。

const my_base *func2(const my_derive *my_ptr) 
{ 
    return (const my_base *)my_ptr; 
    // return (my_base *)my_ptr; 
} 

由于my_ptr已经是一个常量指针,将与(my_base *)铸造它涉及对返回时,取出常量和另一个隐含的const_cast const_cast类型转换?

是否有任何理由将“const”添加到整数函数参数,因为更改它永远不会影响函数外部的状态?

void func3(const int i) 
{ 
    // i = 0; is not allowed, but why, as it is harmless? 
} 

如何在投射整数时加入“const”?我认为这应该类似于func2()

void func4(short i) 
{ 
    const unsigned int j = (const unsigned int) i; 
    // const unsigned int j = (unsigned int) i; 
} 

纠正我,如果我错了。考虑到类型转换可能是一个常见问题解答,我不确定这个问题是否与其他问题重复。谢谢!

+2

这个问题提到了“C/C++”,这是一个坏主意。特别是在这里,因为虽然C和C++都有一个“const”关键字,但它的含义却非常不同。 – Gilles 2010-08-06 18:34:07

回答

6

在铸造类型中添加const关键字意味着结果将保持不变。下面将不是在C++编译(在C它没有任何效果):

int* x = (const int*)malloc(10); // cannot convert from 'const int *' to 'int *' 

你真的不应该在你的C++代码用C型铸造。这是不安全的,应该只用于与传统C代码的兼容性。您应该使用C++强制转换。

func3的情况下,通常const限定符未被使用。如果函数参数没有指针或没有引用类型,那么将const限定符添加到函数参数没有什么大的理由。考虑以下几点:

void func3(  TYPE i); // no reason to use `const` 
void func3(const TYPE& i); // use `const`, so as not to accidentally change `i` 

当您指定左值到右值,如func4,没有必要明确指定中投表达const预选赛。左值到右值的转换将根据C++标准4.1隐式执行。

+0

'malloc'示例很有趣。相反,即使在C++中也是如此:'int a = 0; int b =(const int)a;'我知道在C++中使用C cast是不安全的。我提出这个问题只是在理论上讨论C铸造的正确用法。我总是使用const引用来最小化参数传递成本并避免NULL指针。我可以理解,分配发生时可能存在隐式转换。如果我错过括号中的“const”,是否会产生额外的成本? 谢谢! – 2010-08-06 08:04:01

+0

编译时间或...的额外成本? – 2010-08-06 08:24:24

+0

因此,C型铸造没有运行时间成本,对吧? – 2010-08-06 16:41:41

1

在第一个例子中,在需要const的函数中返回non-const会再次捕获它,这意味着const是重要的,但是你不能注意到它,因为如果它不存在,它将被添加。
在第二个例子中,它将会保持常量。
在第三个例子中,它是不允许的,因为它是无害的:我会改变其余的功能和不可恢复。
请记住,将类型放入不是它的类型的容器中将自动调用自动放置与int放在长字段中相同将不会保持int。
你还必须记住,const意味着与私有或公开的汇编程序相同,这不算什么。生成的汇编程序代码完全不会有差别,无论您将const放在哪里,都将以相同的速度运行。

+0

你的意思是在铸造时明确写出“const”以最大限度地降低成本更好吗?对于函数参数之一,正如*安东尼*所提到的,是否将“const”放在函数实现者的关注中,因此我认为额外的“const”在使用外部库时不会造成问题。谢谢! – 2010-08-06 08:12:35

+0

没有什么可以最小化的,除非投射操作符,否则投射什么也不做。所有的铸造都是在编译时进行的,以保证类型安全。只有像int那样的将double或char *转换为std :: string需要时间,即使在继承中投射也不会执行任何操作。这完全是为了类型安全,并且不会生成汇编代码。 – Dani 2010-08-06 19:36:17

5

const添加到演员表就像将const添加到任何其他类型说明符---结果对象是const。这意味着什么取决于上下文。如果您在顶层添加const(例如,const intconst fooint* const,那么您只有const对象。在大多数情况下,可以复制和分配对象,就像非const对象一样(尽管有一些例外,如std::auto_ptr )。

如果添加const一个指针,那么你也可以将其添加到被指向的类型。例如int * constconst指针到一个纯int,而const int*int const*是一个普通的指针const int

int i; 
int* p = (int* const) &i; // fine; top-level const not a problem 
int* p2 = (int const*) &i; // error; pointed-to object is const, so this is preserved 
int const* p3= (int const*) &i; // OK 

const参数声明中的顶层与声明任何其他局部变量const ---不能修改函数体内的命名对象。但是,const不构成函数类型的一部分,所以您可以在没有(至少符合编译器的情况下)前向声明该函数。

void func(int i); // forward-declare func 
void func(const int i) // this matches the declaration 
{ 
    // i is const here 
} 

这可以说是良好的作风---变量是否被视为const里面的功能是实现细节,因此不应该在原型。在定义中,如果您不打算修改它,则遵循声明const的指导原则。

使用const参数声明别处(例如,作为指针的一部分)会影响函数类型,如石膏。