我在Image.cpp中有一些代码:
Image::Image( int width, int height, int depth ) : m_sFileName(0)
{
...
}
and in Image.h:
class Image: public DrawAble, public RenderAble
{
...
private :
std::string *m_sFileName;
};
我的问题是:第一行m_sFilename
发生了什么?我猜它被设置为NULL,但这样做的重点是什么。它会是一样的:
Image::Image( int width, int height, int depth )
{
m_sFileName(0);
...
}
答案 0 :(得分:11)
第一个使用所谓的initialization list。
当您输入构造函数的主体时,必须构造所有类成员(因此可以使用它们)。所以如果你有这个:
class Foo
{
public:
Foo()
: str() // this is implicit
{
str = "String.";
}
private:
std::string str;
};
因此,str
被构造,然后被分配。更好的是:
class Foo
{
public:
Foo()
: str("String.")
{
}
private:
std::string str;
};
这样就可以直接构造str
。这对你的情况没有影响,因为指针没有构造函数。
通常认为在构造函数中使用初始化列表而不是运行代码是一种好习惯。 初始化列表应该用于初始化,构造函数应该用于运行代码。
另外,为什么要使用指向字符串的指针?如果你想要一个字符串,使用一个字符串;不是指向字符串的指针。有可能,你真的想要一个字符串。
有关初始化列表的更多信息:
初始化列表比初始化类成员有更多用途。它们可用于将参数传递给基础构造函数:
class Foo
{
public:
Foo(int i) { /* ... */ }
}
class Bar
: public Foo
{
public:
Bar()
: Foo(2) // pass 2 into Foo's constructor.
// There is no other way of doing this.
{
/* ... */
}
};
或不变成员:
class Foo
{
public:
Foo()
: pi(3.1415f)
{
pi = 3.1415f; // will not work, pi is const.
}
private:
const float pi;
};
或参考:
class Foo
{
public:
Foo(int& i)
: intRef(i) // intRef refers to the i passed into this constructor
{
intRef = i; // does *not* set intRef to refer to i!
// rather, it sets i as the value of
// the int intRef refers to.
}
private:
int &intRef;
};
答案 1 :(得分:2)
这称为初始化程序。你应该习惯使用它们。在这种情况下,无所谓。但在其他情况下,不使用它们可能意味着非指针成员的双重初始化。首先使用默认值,然后使用您的值。 最后是没有没有参数的构造函数的成员的情况。在这些情况下,您别无选择,只能使用初始化程序。
答案 2 :(得分:0)
这与做
相同Image::Image( int width, int height, int depth )
{
m_sFileName = 0;
// ...
}
请注意,使用指向std::string
的指针通常不是一个好主意,因为空字符串是一个同样好的没有任何标记,如果你做它,你不必关心破坏普通会员。
答案 3 :(得分:0)
m_sFileName(0)
构造函数体中的将被解释为调用名为m_sFileName的函数。您可以用
替换它m_sFileName = 0;
但是,建议的初始化位于构造函数的初始化列表中,就像第一个示例中一样。未在构造函数的初始化列表中初始化的任何数据成员将使用其类型的默认构造函数自动初始化。
答案 4 :(得分:0)
它与:
相同Image::Image( int width, int height, int depth )
{
m_sFileName = 0;
...
}
答案 5 :(得分:0)
您正在使用的语法:
Image::Image( int width, int height, int depth ) : m_sFileName(0)
{
...
}
称为初始化列表。它会将值0赋给您的成员变量。
使用m_sFileName = 0;在构造函数体中性能较低,因为该成员将被初始化两次(因为它不包含在初始化列表中,所以一次自动初始化,第二次用于显式初始化)。
答案 6 :(得分:0)
这两个变体几乎相同 - 你是正确的
: m_sFileName(0)
导致m_sFileName
初始化为0
。
当您想要创建const Image
时,C ++具有此特殊初始化语法的原因变得非常重要。 (在这种情况下可能不是你想要做的事情,但它可能是你想要为“轻量级”类型做的事情。)对于const Image
,this
也是构造函数中的const指针与每个“普通”成员函数一样,因此不允许m_sFileName=0
。
为了解决这个问题,C ++有初始化列表,它们执行初始化而不是赋值。顺便说一句,如果m_sFileName
是一个对象,除了const
注意事项之外还会有一个额外的区别:初始化列表会导致m_sFileName
的构造函数被调用,而赋值会调用赋值运算符。
除了所有这些考虑因素之外,初始化列表是传达意图的好方法 - 表示您正在初始化,而不是分配。