使用C ++重构 [英] Refactoring with C++ 11

查看:286
本文介绍了使用C ++重构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于c ++大量程序员提供了新的工具集,旨在简化代码,提高表达力,提高效率,浏览旧代码并做出调整(有些毫无意义,一些成功)来实现他们的目标。虽然试图不让这么多劳动的时间浪费太多时间,只是做出非侵入性和自我改变,最好的做法是什么?



让我详述一下:




  • 使用 auto 运行基于迭代器的循环:

      for(std :: vector< foo> :: const_iterator it lala.begin()),ite(lala.end()); it!= ite; 
    ++ it);
    //成为
    for(auto it(lala.cbegin()),ite(lala.cend()); it!= ite; ++ it);


  • 使用 tie 代码行(如何分配多个值立即转换为结构体

      a = 1; 
    b = 2;
    c = 3;
    d = 4;
    e = 5;
    //成为
    std :: tie(a,b,c,d,e)= std :: make_tuple(1,2,3,4,5);


  • 要使类不可继承,只需将其声明为final实现了这样的行为 http://www.parashift.com/c++-faq/final-classes.html

  • 使用delete关键字显式隐藏构造函数/析构函数,而不是将它们声明为私有(例如创建基于堆的对象,非可复制对象等的代码)


  • 转换琐碎函数只是为了将单个STL算法执行到 lambda 函数中(除了减少代码,

  • >
  • 取消bind1st,bind2nd,只需使用绑定


  • 对于类型traits(Is_ptr_but_dont_call_for_const_ptrs>和这样的:)),其具有由<

    b
  • 向类提供移动语义(虽然这不会成为肮脏/快速/轻松的更改)


  • nullptr 在可能的地方,而不是NULL宏,摆脱的代码,填充指针的容器0的转换为对象类型

      std :: vector< foo *> f(23); 
    for(std :: size_t i(0); i <23; ++ i)
    {f [i] = static_cast< foo *> }
    //变为
    std :: vector< foo *> f(23,nullptr);


  • 清除向量资料存取语法

      std :: vector< int> vec; 
    & vec [0]; //将数据访问为C风格数组
    vec.data(); //用上面的新方法


  • / strong>(除了避免使用已弃用的异常规范外,您还可获得一些速度优势 http: //channel9.msdn.com/Events/GoingNative/2013/An-Effective-Cpp11-14-Sampler @ 00.29.42)

      void some_func()noexcept; //更多优化选项
    void some_func()throw(); // less optimization options
    void some_func(); // less optimization options


  • 更换代码,希望优化器将使用emplace函数(如果可用)来将复制品移开,以便完美地转发参数,并将对象直接构造到容器中,而不需要临时。

      vecOfPoints.push_back(Point(x,y,z)); // so '03 
    vecOfPoints.emplace_back(x,y,z); //未执行复制或移动操作






Shafik Yaghmour的回答被授予奖励受到观众的最大接受。



R Sahu的回答是我接受的,因为其提议的组合功能捕获 重构精神

解决方案

我将添加委托构造函数和类中的成员初始化器到列表中。



通过使用委托构造函数和类内初始化简化



+03:

  class A 
{
public:

默认构造函数以及复制构造函数需要
//初始化一些成员几乎相同,并调用init()到
// finish构造。
A(double data):id_(0),name_(),data_(data){init();}
A(const& copy) data_(copy.data_){init();}

void init()
{
id_ = getNextID();
name_ = getDefaultName();
}

int id_;
string name_;
double data_;
};

使用C ++ 11:

  class A 
{
public:

//使用委托构造函数,复制构造函数可以
//重用此构造函数,避免重复代码。
//在线初始化负责初始化成员。
A(double data):data_(data){}

A(copy.data_){}

int id_ = getNextID();
string name_ = getDefaultName();
double data_;
};


Given the new toolset provided by c++ lots of programmers, aiming at code simplification, expressiveness, efficiency, skim through their old code and make tweaks (some pointless, some successful) to achieve their goals. Whilst trying not to loose too much time on such labors and just make non intrusive and self contained changes, what are the best practices?

Let me cross out the obvious :

  • Use auto to run iterator based loops :

    for (std::vector<foo>::const_iterator it(lala.begin()), ite(lala.end()); it != ite;     
    ++it);
    // becomes
    for (auto it(lala.cbegin()), ite(lala.cend()); it != ite; ++it);
    

  • Use tie for multiple assignments that just produce C-style rows of code ( how to assign multiple values into a struct at once? )

    a = 1;
    b = 2; 
    c = 3;
    d = 4; 
    e = 5;
    // becomes
    std::tie(a, b, c, d, e) = std::make_tuple(1, 2, 3, 4, 5);
    

  • To make a class non inheritable just declare it as "final" and delete the code that achieved such a behavior http://www.parashift.com/c++-faq/final-classes.html

  • Use the delete keyword to explicitly hide constructors/destructors instead of declaring them private (eg code to create heap based objects, non copyable objects etc)

  • Turn trivial functors created just to facillitate the execution of a single STL algorithm into lambda functions (apart from reducing code cluttering you'll have guaranteed inlined calls)

  • Simplify RAII wrapping of an object by just using a smart pointer

  • Get rid of bind1st, bind2nd and just use bind

  • Replace hand written code for type traits (Is_ptr_but_dont_call_for_const_ptrs<> and such :) ) with standard code provided by < type_traits >

  • Stop including boost headers for functionallity now implented in STL (BOOST_STATIC_ASSERT vs static_assert)

  • Provide move semantics to classes (although this wouldn't qualify as a dirty/quick/easy change)

  • Use nullptr where possible instead of the NULL macro and get rid of the code that filled containers of pointers with 0's casted to object type

    std::vector<foo*> f(23);
    for (std::size_t i(0); i < 23; ++i)
    { f[i] = static_cast<foo*>(0); }
    // becomes
    std::vector<foo*> f(23, nullptr);
    

  • Clear the vector data accessing syntax

    std::vector<int> vec;
    &vec[0];    // access data as a C-style array
    vec.data(); // new way of saying the above
    

  • Replace throw() with noexcept (apart from avoiding the deprecated exception specifiation you get some speed benefits http://channel9.msdn.com/Events/GoingNative/2013/An-Effective-Cpp11-14-Sampler @ 00.29.42)

    void some_func() noexcept; // more  optimization options
    void some_func() throw();  // fewer optimization options
    void some_func() ;         // fewer optimization options
    

  • Replace code where you'd push a tempory in a container and hoped that the optimizer would ellide the copy away, with an "emplace" function where available, in order to perfectly forward the argument and construct directly an object into a container without temporary at all.

    vecOfPoints.push_back(Point(x,y,z)); // so '03
    vecOfPoints.emplace_back(x, y, z);   // no copy or move operations performed
    

UPDATE

The answer by Shafik Yaghmour was rightfully awarded the bounty for having the greatest acceptance by the audience.

The answer by R Sahu was my accepted one, because the combination of features it proposes captures the spirit of refactoring : making code clearer and cleaner and simpler and elegant.

解决方案

I would add delegating constructors and in-class member initializers to the list.

Simplification By Using Delegating Constructors and In-Class Initialization

With C++03:

class A
{
  public:

    // The default constructor as well as the copy constructor need to 
    // initialize some of the members almost the same and call init() to
    // finish construction.
    A(double data) : id_(0), name_(), data_(data) {init();}
    A(A const& copy) : id_(0), name_(), data_(copy.data_) {init();}

    void init()
    {
       id_ = getNextID();
       name_ = getDefaultName();
    }

    int id_;
    string name_;
    double data_;
};

With C++11:

class A
{
  public:

    // With delegating constructor, the copy constructor can
    // reuse this constructor and avoid repetitive code.
    // In-line initialization takes care of initializing the members. 
    A(double data) : data_(data) {}

    A(A const& copy) : A(copy.data_) {}

    int id_ = getNextID();
    string name_ = getDefaultName();
    double data_;
};

这篇关于使用C ++重构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆