tag 标签: initialization

相关博文
  • 热度 8
    2011-6-16 13:51
    1694 次阅读|
    0 个评论
    In C++, a constructor is a special class member function that allows guaranteed initialisation for objects of its class type. In my recent articles, I've been discussing what constructors are and what kind of code compilers generate on their behalf. 1, 2 Last month, I started to explain the behaviour of constructors for classes with members that have constructors of their own. 3 This month, I'll pick up where I left off. Although C doesn't support constructors, C programs can provide functions that mimic constructors. Well-written C programs do. As in the past, I'll explain the behaviour of C++ constructors by presenting C code that exhibits much the same behaviour. This should help you see not only what C++ is doing behind the scenes, but also show how you can emulate constructors in C. Assignment vs. initialisation For my example, I've been using a class for entries in a symbol table, where each entry stores a name and an associated ID and a value. The name is a character string, the ID is an unsigned integer value, and the value is a sequence of one or more signed integer values. The entry class definition looks in part like: class entry { entry(string const n, int v); ~~~ private: static unsigned counter; string name; unsigned id; sequence value; }; Here, string might be the Standard C++ string class, or something similar. The sequence class might actually be a typedef alias for a standard container class template specialization, such as: typedef vector sequence; or it might be a custom-built class. A class can have more than one constructor. At the moment, the entry class has just one, declared as: entry(string const n, int v); This constructor initializes an entry so that its name is n and its value is v . The constructor also uses static member counter to generate a unique ID for each entry . The constructor definition that I presented last time looked like: entry::entry(string const n, int v) { name = n; value.push_back(v); id = ++counter; } Strictly speaking, the first statement in the constructor body is not an initialisation. It's an assignment that replaces name 's value, assuming the string has already been initialized. Calling push_back is not an initialisation, either. It assumes that value already has an initial value, and appends one more value to whatever's already there. Remember, entry 's members name and value have class types. Those classes have constructors, which provide guaranteed initialisation. C++ preserves the guarantee by inserting default constructor calls for entry 's members into the entry constructor itself. (A default constructor is a constructor that can be called with an empty argument list.) The compiler generates a call that applies the default string constructor to entry 's member name , and another call that applies the default sequence constructor to member value . A C function that performs the same work as the entry constructor might look like: void entry_construct_nv (entry *_this, string const *n, int v) { string_construct(_this-name); sequence_construct(_this-value); string_copy(_this-name, n); sequence_push_back(_this-value, v); _this-id = ++counter; } As the C code indicates, the entry constructor initializes name to be an empty string, only to replace the empty string with a copy of n . Similarly, it initializes value to be an empty sequence, only to append the value of v . The constructor code would be shorter and faster if the constructor simply initialized name with a copy of n and value as a sequence containing just v . C++ provides member initializers to eliminate such unnecessary default initialisation. Member initializers Again, the entry class has two members of class type, name and value . C++ upholds the initialisation guarantee by applying the default constructors to name and value as part of the entry constructor. If you'd like the entry constructor to apply different constructors to its members, it must use member initializers. A constructor definition may include a list of member initializers. Each member initializer specifies the initial value for some class member. For example, in: entry::entry(string const n, int v) : name (n), value (1, v) { id = ++counter; } the member initializer name (n) specifies that this entry constructor will initialise its member name using the string copy constructor with n as its argument. The member initializer value (1, v) specifies that the entry constructor will initialise value using a sequence constructor that accepts 1 and v as its arguments. This will initialise the sequence to contain one element whose value is v . Using member initializers often streamlines the work of a constructor. In this case, it eliminates statements from the constructor body. A C function that performs the same work as this entry constructor has fewer function calls than it did before: void entry_construct_nv (entry *_this, string const *n, int v) { string_construct_copy(_this-name, n); sequence_construct_cv(_this-value, 1, v); _this-id = ++counter; } Member initializers can appear only in constructors, not in any other functions. If present, the member initializer list must appear after the closing parenthesis of the constructor's parameter list and before the opening brace of the function body. If a constructor has any member initializers, a colon (":") must appear before the first one. Different programmers have different styles for formatting member initializer lists. I like to place the colon immediately after the parameter list and place the member initializers on the line that follows. Each member initializer has the general form: member-name ( expression-list ) where member-name is the name of a class member and expression-list is a list of zero or more expressions separated by commas. If the initializer names a member of class type, the expression list can be any sequence that's acceptable as the argument list to one of the constructors for that member. Whenever possible, C++ strives to treat objects of class and non-class types according to uniform rules. Thus, you can use member initializers to initialise members of non-class type. Typically when a member initializer has the form m (v) and m has a non-class type, the member initializer generates the same code as the assignment: m = v; appearing in the constructor body. For example, you can write the previous constructor definition as: entry::entry(string const n, int v): name (n), id (++counter) , value (1, v) { } and it generates the same code as before. It's not uncommon for a C++ constructor to have an empty function body and do all the work in the member initializers. When a member has a const-qualified type, you must use a member initializer to initialise that member. For example, if you declare the id member in the entry class to be const , as in: class entry { ~~~ unsigned const id; sequence value; }; then any statement that tries to modify id won't compile, even in a constructor: entry::entry(string const n, int v): name (n), value (1, v) { id = ++counter; // error if id is const } The only way to initialise such a const member is with a member initializer. The same is true for members of a reference type. Less to be surprised about One of the easiest ways to misuse an object in C is to fail to initialise it properly. In C++, you can use constructors to guarantee initialisation, thus getting the compiler to do automatically what you might forget to do yourself. Unfortunately, fear about guaranteed initialisation leads some programmers to shy away from C++, claiming that C++ does too much behind the scenes. Using member initializers offers more control over what constructors do, and helps eliminate unnecessary default initialisation. Endnotes: 1. Saks, Dan, "Demystifying constructors," Embeddeddesignindia.co.in , April 2011. http://forum.embeddeddesignindia.co.in/BLOG_ARTICLE_7113.HTM 2. Saks, Dan, "Constructors and object definitions," Embeddeddesignindia.co.in , April 2011. http://forum.embeddeddesignindia.co.in/BLOG_ARTICLE_7323.HTM 3. Saks, Dan, "Understanding member initialisation," Embeddeddesignindia.co.in , May 2011. http://forum.embeddeddesignindia.co.in/BLOG_ARTICLE_7818.HTM  
相关资源
  • 所需E币: 1
    时间: 2020-12-31 19:14
    大小: 11.19KB
    上传者: Argent
    随着FPGA技术的不断发展,许多消费类产品都嵌入了FPGA程序,ZYNQ架构属于主流,搜集的部分有关FPGA学习资料,希望对您有所帮助,欢迎下载。
  • 所需E币: 3
    时间: 2019-12-24 23:11
    大小: 299.77KB
    上传者: 微风DS
    将LPC2000设备作为应用目标提供初始化步骤,降低功耗的提示以及代码示例AN10404Initializationcode/hintsfortheLPC2000familyRev.01―1November2005ApplicationnoteDocumentinformationInfoContentKeywordsARMassemblycode,Initialization,Clock,Stack,powerconsumptionAbstractProvidesinitializationsteps,hintsforreducingpowerconsumptionandcodeexamplesthatwouldgettheLPC2000devicereadyforthetargetapplicationPhilipsSemiconductorsAN10404Initializationcode/hintsfortheLPC2000familyRevisionhistoryRevDateDescription……