Can the use of C++11's 'auto' deteriorate performance or even break the code?

試著忘記壹切 提交于 2019-12-21 19:45:26

问题


This question is the opposite of an existing question "Can the use of C++11's 'auto' improve performance?"

One of the answers to that question indicated that usage of auto can have not only positive but also negative effects.

I believe we need a separate question, with answers focusing on that side of auto.


回答1:


With auto there is no conversion at the variable declaration+initialization line. But if such conversion must happen anyway, it better happen once during initialization than multiple times later.

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

Such a deferred conversion may break the code when auto is combined with lazy evaluation (real world example 1, example 2):

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'



回答2:


Your question title specifies 'performance'.

auto is a compile time construct that allows itself to be substituted with a deduced type. Its use doesn't result in different machine instructions, than if you have hand-written the typename it deduced.

The problem is that, in managing performance, type specification and casting is often crucial, and auto can hide that leading programmers to say something different than they intended:

std::vector<std::array<BigStruct, 10000>>& f();
auto va = f();  // copy
for (auto v: va) {  // copies
    // ...
}

if the programmer had written:

std::vector<std::array<BigStruct, 10000>> va = f();

or

for (std::array<BigStruct, 10000> v : va)

they would have recognized they were specifying by-value. But std::array<BigStruct, 10000> is what auto deduces here and in these cases that translates to by-value.

People drop their guard and forget that auto deduces the type, it doesn't include the ref qualification.

auto& va = f();  // reference
for (auto& v : va) {  // references

There was a performance affect here, but it wasn't caused by auto it was a side-effect of (accidentally) explicitly specifying a copy.

auto doesn't mean the same as this it means 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.



回答3:


Blind search-and-replace of all type declarations by auto can be a head-ache, whenever braced initialization is used:

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
}

The first declaration of variable p is correctly deduced as a call to the constructor accepting two integers. But the auto variable q searches for a constructor requiring std::initializer_list<int> and hence fails to compile.



来源:https://stackoverflow.com/questions/38415831/can-the-use-of-c11s-auto-deteriorate-performance-or-even-break-the-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!