使用 C++11 的 'auto' 会降低性能甚至破坏代码吗?
Can the use of C++11's 'auto' deteriorate performance or even break the code?
此问题与现有问题“”相反。
这个问题表明使用 auto
不仅可以产生积极的影响,也可以产生消极的影响。
我认为我们需要一个单独的问题,答案侧重于 auto
。
对于auto
,变量声明+初始化行没有转换。但是,如果这种转换无论如何都必须发生,那么最好在初始化期间发生一次,而不是之后多次发生。
struct X {
...
};
struct Y {
operator X() const;
...
};
Y foo(); // maybe, originally its return type was X but later was changed to Y
void bar(const X& );
const auto x = foo(); // <-- conversion not happening here
//
for ( int i = 0; i < 100; ++i ) //
bar(x); // <-- silently rages here
当 auto
与惰性求值(真实世界 example 1, )结合使用时,这种延迟转换可能会破坏代码:
class Matrix { ... };
class MatrixExpression {
...
operator Matrix() const;
};
MatrixExpression operator+(const Matrix& a, const Matrix& b);
std::ostream& operator(std::ostream& out, const Matrix& m);
Matrix a = ...;
Matrix b = ...;
auto c = a + b; // evaluation of the matrix addition doesn't happen here
a[0][0] += 1;
std::cout << c; // matrix addition is evaluated here, using the new state of 'a'
您的问题标题指定 'performance'。
auto
是一个编译时构造,它允许自己被推导的类型替换。它的使用不会导致不同的机器指令,如果你有 hand-written 它推导出的类型名。
问题是,在管理性能时,类型规范和转换通常是至关重要的,auto
可以隐藏导致程序员说出与他们预期不同的话:
std::vector<std::array<BigStruct, 10000>>& f();
auto va = f(); // copy
for (auto v: va) { // copies
// ...
}
如果程序员写了:
std::vector<std::array<BigStruct, 10000>> va = f();
或
for (std::array<BigStruct, 10000> v : va)
他们会意识到他们指定的是 by-value。但是 std::array<BigStruct, 10000>
是 auto
在这里推导出来的,在这些情况下转化为 by-value.
人们放松警惕,忘记了 auto
推导出 类型 ,它不包括 ref 资格。
auto& va = f(); // reference
for (auto& v : va) { // references
此处对性能有影响,但这不是由 auto
引起的,而是 side-effect(意外地)明确指定了一个副本。
auto
并不意味着 the same as this
它意味着 an instance of this
.
auto va = f(); // an instance-of what f returns, thus a copy.
auto& va = f(); // a reference to an instance-of, thus by reference.
使用 auto 的所有类型声明的盲目搜索和替换可能是一个令人头疼的问题,每当使用花括号初始化时:
class Point
{
public:
Point (int x1, int y1) { x = x1; y = y1; }
private:
int x, y;
};
int main()
{
Point p{5, 6};
auto q{5, 6}; // Error. Uniform initialization is not REALLY uniform
}
变量 p 的第一个声明被正确地推断为对接受两个整数的构造函数的调用。但是 auto 变量 q 搜索需要 std::initializer_list<int
>[ 的构造函数=21=] 因此编译失败。
此问题与现有问题“
auto
不仅可以产生积极的影响,也可以产生消极的影响。
我认为我们需要一个单独的问题,答案侧重于 auto
。
对于auto
,变量声明+初始化行没有转换。但是,如果这种转换无论如何都必须发生,那么最好在初始化期间发生一次,而不是之后多次发生。
struct X {
...
};
struct Y {
operator X() const;
...
};
Y foo(); // maybe, originally its return type was X but later was changed to Y
void bar(const X& );
const auto x = foo(); // <-- conversion not happening here
//
for ( int i = 0; i < 100; ++i ) //
bar(x); // <-- silently rages here
当 auto
与惰性求值(真实世界 example 1,
class Matrix { ... };
class MatrixExpression {
...
operator Matrix() const;
};
MatrixExpression operator+(const Matrix& a, const Matrix& b);
std::ostream& operator(std::ostream& out, const Matrix& m);
Matrix a = ...;
Matrix b = ...;
auto c = a + b; // evaluation of the matrix addition doesn't happen here
a[0][0] += 1;
std::cout << c; // matrix addition is evaluated here, using the new state of 'a'
您的问题标题指定 'performance'。
auto
是一个编译时构造,它允许自己被推导的类型替换。它的使用不会导致不同的机器指令,如果你有 hand-written 它推导出的类型名。
问题是,在管理性能时,类型规范和转换通常是至关重要的,auto
可以隐藏导致程序员说出与他们预期不同的话:
std::vector<std::array<BigStruct, 10000>>& f();
auto va = f(); // copy
for (auto v: va) { // copies
// ...
}
如果程序员写了:
std::vector<std::array<BigStruct, 10000>> va = f();
或
for (std::array<BigStruct, 10000> v : va)
他们会意识到他们指定的是 by-value。但是 std::array<BigStruct, 10000>
是 auto
在这里推导出来的,在这些情况下转化为 by-value.
人们放松警惕,忘记了 auto
推导出 类型 ,它不包括 ref 资格。
auto& va = f(); // reference
for (auto& v : va) { // references
此处对性能有影响,但这不是由 auto
引起的,而是 side-effect(意外地)明确指定了一个副本。
auto
并不意味着 the same as this
它意味着 an instance of this
.
auto va = f(); // an instance-of what f returns, thus a copy.
auto& va = f(); // a reference to an instance-of, thus by reference.
使用 auto 的所有类型声明的盲目搜索和替换可能是一个令人头疼的问题,每当使用花括号初始化时:
class Point
{
public:
Point (int x1, int y1) { x = x1; y = y1; }
private:
int x, y;
};
int main()
{
Point p{5, 6};
auto q{5, 6}; // Error. Uniform initialization is not REALLY uniform
}
变量 p 的第一个声明被正确地推断为对接受两个整数的构造函数的调用。但是 auto 变量 q 搜索需要 std::initializer_list<int
>[ 的构造函数=21=] 因此编译失败。