常见错误56:直接与复制初始化
标准允许编译器执行某种代码变换,去除这个临时对象的初始化和复制构造函数的调用,
以产生和直接初始化一模一样的目标码。这是一个不平凡的优化,因为代码的实际行为改变了。
大多数C++编译都会做代码变换,但标准并没有强制要求这么做。
代码变换需要了解编译器是在校验过原始代码的语义之后才实施变换的。
为了让代码更简单,更具可移植性,一个较佳的做法是在class对象,或“有可能是class
标准允许编译器执行某种代码变换,去除这个临时对象的初始化和复制构造函数的调用,
以产生和直接初始化一模一样的目标码。这是一个不平凡的优化,因为代码的实际行为改变了。
大多数C++编译都会做代码变换,但标准并没有强制要求这么做。
代码变换需要了解编译器是在校验过原始代码的语义之后才实施变换的。
为了让代码更简单,更具可移植性,一个较佳的做法是在class对象,或“有可能是class
对象之实体”的声明语句中直接初始化。
seqlength.cpp
#include <iostream>
template <typename N, typename In>
void seqLength( N &len, In b, In e ) {
N n( 0 ); // 这样写, 不要写成 "N n = 0;"
while( b != e ) {
++n;
++b;
}
len = n;
}
//在这个实现中,直接初始化的采用使得我们能够处理自定义的、禁止进行复制构造的数值
//类型。
class StrangeInt {
public:
StrangeInt( int a = 0 )
: v_( a ) {}
StrangeInt &operator =( const StrangeInt &rhs )
{ v_ = rhs.v_; return *this; }
StrangeInt &operator ++()
{ ++v_; return *this; }
const StrangeInt operator ++(int)
{ StrangeInt temp( *this ); ++*this; return temp; }
operator int() const
{ return v_; }
private:
int v_;
StrangeInt( const StrangeInt &that )
: v_( that.v_ ) {}
};
int main() {
int a[] = { 1,2,3,4,5,6};
int len;
seqLength( len, a, a+6 );
std::cout << len << std::endl;
StrangeInt len2;
seqLength( len2, a, a+6 );
std::cout << len2 << std::endl;
getchar();
return 0;
}
输出
6
6