C ++ language based encountered in the work and common errors

History and standard C ++

Here a brief column about C++several major events, and I often use the typical characteristics of the development process, each supported by the standard details can be found in the ISO standard document.

  • C With Classes: Support basic C ++ language features, including multi-state, exception handling, templates, namespaces, etc.
  • C++98: STL, RTTI, templates, exception handling, and other standard library implementation
  • C++03: Repair defects in the 98 C ++ and support TR1
  • C++11:auto、range-for、rvalue、lambda、shared_ptr、concurrent
  • C++14: Variable templates, and enhanced multi-state lambda library implementation
  • C++17: Folding expression derived class template argument
  • C++20: <=>, Coroutine, concepts

Parameter passing and return values

  • Avoid temporary variables lead to redundancy costs
int setupMVAudioStream(std::string path);                    // BAD
int setupMVAudioStream(std::string const& path);    // GOOD
  • Determine characteristic RVO return value class object
// 如果此时函数体实现编译器未使用RVO,则会出现冗余性能开销,BAD
std::list<MVStreamOption*> generateMVStreamList(std::list<MVStreamOption*> *optionList);

// 使用引用传递参数返回结果,不会出现冗余性能开销,GOOD
void generateMVStreamList(std::list<MVStreamOption*>& outList,
                          std::list<MVStreamOption*> *optionList);
  • Function has to be given explicitly return value return type, avoid using the wrong end of the external function does not return a value or the normal execution
int EditorService::updateRenderStreams(FileStreamList &streamList)
{
    // 执行一些操作,没有return语句或者存在多个可能无法执行到的非全局生存期return语句
    if (condition)
    {
        return -1;    // 当condition为false时不执行
    }
    // BAD
}

// 始终应该存在一个函数内全局生存期的return语句,避免其它非全局生存期的return语句未执行
int EditorService::updateRenderStreams(FileStreamList &streamList)
{
    // 执行一些操作,可能存在多个多生存期管理的return语句
    if (condition)
    {
        return -1;    // 当condition为false时不执行
    }
    return 0;    // GOOD
}
  • It should return a reference to the return class member variable or constant reference or pointer
// BAD,调用unordered_map的拷贝构造函数导致额外性能开销
std::unordered_map<Node*, int> Node::GetActiveChildren()
{
    return mActiveChildren;
}

// GOOD,返回引用和常量引用,不会产生临时对象
std::unordered_map<Node*, int>& Node::GetActiveChildren()
{
    return mActiveChildren;
}
std::unordered_map<Node*, int> const& Node::GetActiveChildren() const
{
    return mActiveChildren;
}

Statement virtual base class destructor avoid memory leaks

struct Base {  // BAD: implicitly has a public nonvirtual destructor
    virtual void f();
};

struct D : Base {
    string s {"a resource needing cleanup"};
    ~D() { /* ... do some cleanup ... */ }
    // ...
};

void use()
{
    unique_ptr<Base> p = make_unique<D>();
    // ...
} // p's destruction calls ~Base(), not ~D(), which leaks D::s and possibly more

Construction and destructor avoid virtual function call

class Base {
public:
    virtual void f() = 0;   // not implemented
    virtual void g();       // implemented with Base version
    virtual void h();       // implemented with Base version
};

class Derived : public Base {
public:
    void g() override;   // provide Derived implementation
    void h() final;      // provide Derived implementation

    Derived()
    {
        // BAD: attempt to call an unimplemented virtual function
        f();

        // BAD: will call Derived::g, not dispatch further virtually
        g();

        // GOOD: explicitly state intent to call only the visible version
        Derived::g();

        // ok, no qualification needed, h is final
        h();
    }
};

Priority use initialization list rather than an assignment to construct the object

class B {   // BAD
    string s1;
public:
    B(const char* p) { s1 = p; }   // BAD: default constructor followed by assignment
    // ...
};

class C {   // UGLY, aka very bad
    int* p;
public:
    C() { cout << *p; p = new int{10}; }   // accidental use before initialized
    // ...
};

class D {   // Good
    string s1;
public:
    A(string_view v) : s1{v} { }    // GOOD: directly construct
    // ...
};

Increases as the return type is derived using cv auto modified to avoid temporary variables

std::unordered_map<Node*, int> const& Node::GetActiveChildren() const
{
    return mActiveChildren;
}

// BAD: 此时children类型实际为std::unordered_map<Node*, int>,退化为采用模板类型推导没有cv属性
auto children = node->GetActiveChildren();

Alternatively the interface preferentially used emplace push / insert improve performance

std::list<std::string> ls;
std::string s("abc");

ls.push_back(s);                        // BAD
ls.push_back(std::move(s));    // GOOD

ls.push_back("abc");                // GOOD
ls.emplace_back("abc");            // BETTER

Use make_unique / make_shared construction management smart pointer objects

// Not exception-safe: the compiler may interleave the computations of arguments as follows:
//
// 1. allocate memory for Foo,
// 2. construct Foo,
// 3. call bar,
// 4. construct unique_ptr<Foo>.
//
// If bar throws, Foo will not be destroyed, and the memory-allocated for it will leak.
f(unique_ptr<Foo>(new Foo()), bar());    // BAD

// Exception-safe: calls to functions are never interleaved.
f(make_unique<Foo>(), bar());    // GOOD

Code size is determined using the empty container is empty STL

std::list<int> ls;
// ...

// BAD: 不同的STL标准实现稍有差异,比如Android下的list.size的时间复杂度为O(N)
if (ls.size() > 0)
{
    // ...
}

// GOOD:时间复杂度为O(1)
if (!ls.empty())
{
    // ...
}

to sum up

C ++ has many features, but the above are some problems often use a very small part of the course, for example, causing crashes or memory leaks, etc., and can use the higher performance of some of the recommendations, more usage will gradually in subsequent summary come out.

Guess you like

Origin yq.aliyun.com/articles/706423