这可能是一个愚蠢的问题,但我仍然有点好奇......最近我在做我以前的一个同事的项目,我注意到他真的很喜欢使用这样的东西:
int foo(7);
而不是:
int foo = 7;
这是用C++语言做的正常/好方法吗?它有什么好处吗?(或者这只是他喜欢的一些愚蠢的编程风格..?
这真的让我想起了如何在类构造函数中分配类成员变量的好方法......像这样:
class MyClass
{
public:
MyClass(int foo) : mFoo(foo)
{ }
private:
int mFoo;
};
取而代之的是:
class MyClass
{
public:
MyClass(int foo)
{
mFoo = foo;
}
private:
int mFoo;
};
对于基本类型,没有区别。使用与现有代码一致且看起来更自然的那个。
否则
A a(x);
执行直接初始化,以及
A a = x;
执行副本初始化。
第二部分是成员初始值设定项列表,在StackOverflow上有一堆关于它的问答。
两者都有效。对于内置类型,它们执行相同的操作;对于类类型,存在细微差别。
MyClass m(7); // uses MyClass(int)
MyClass n = 3; // uses MyClass(int) to create a temporary object,
// then uses MyClass(const MyClass&) to copy the
// temporary object into n
显而易见的含义是,如果MyClass
没有复制构造函数,或者它有一个但无法访问,则尝试的构造将失败。如果构造成功,则允许编译器跳过复制构造函数并直接使用 MyClass(int)
。
以上所有答案都是正确的。只需添加 C++11 支持另一种方式,即他们所说的初始化变量的通用方式。
int a = {2} ;
或
int a {2} ;
其他几个很好的答案指出了构造"就地"(ClassType v(<constructor args>)
(和创建临时对象并使用复制构造函数复制它(ClassType v = <constructor arg>
(之间的区别。我认为,还需要补充两点。首先,第二种形式显然只有一个参数,所以如果你的构造函数接受多个参数,你应该更喜欢第一种形式(是的,有办法解决这个问题,但我认为直接构造更简洁易读 - 但是,正如已经指出的那样,这是个人偏好(。
其次,如果您的复制构造函数执行与标准构造函数明显不同的操作,则您使用的表单很重要。大多数时候情况并非如此,有些人会争辩说这样做是个坏主意,但语言确实允许这种情况(不过,您最终因此而处理的所有意外都是您自己的错(。
初始化变量C++风格 - C++为基本类型添加了它,因此相同的形式可以用于基本类型和用户定义的类型。 这对于要为任一类型实例化的模板代码非常重要。
是否要将其用于基本类型的正常初始化是一种样式首选项。
请注意,C++11 还添加了统一初始化语法,该语法允许对所有类型使用相同的初始化样式 - 甚至是像 POD 结构和数组这样的聚合(尽管用户定义的类型可能需要具有一种采用初始化列表的新构造函数类型,以允许统一语法与它们一起使用(。
你的问题根本不是一个愚蠢的问题,因为事情并不像看起来那么简单。假设您有:
class A {
public:
A() {}
};
和
class B {
public:
class B(A const &) {}
};
写作
B b = B(A());
要求 B 的复制构造函数可访问。写作
B b = A();
还要求 B 的转换构造函数 B(A const &( 不显式声明。另一方面,如果你写
A a;
B b(a);
一切都很好,但如果你写
B b(A());
编译器将其解释为函数 b 的声明,该函数采用无名称参数,该参数是返回 A 的无参数函数,从而导致神秘的错误。这被称为C++最令人烦恼的解析。
我更喜欢使用括号样式...尽管我总是使用空格来区分函数或方法调用,但我不使用空格:
int foo (7); // initialization
myVector.push_back(7); // method call
我更喜欢全面使用它进行初始化的原因之一是因为它有助于提醒人们这不是一个任务。 因此,赋值运算符的重载将不适用:
#include <iostream>
class Bar {
private:
int value;
public:
Bar (int value) : value (value) {
std::cout << "code path A" << "n";
}
Bar& operator=(int right) {
value = right;
std::cout << "code path B" << "n";
return *this;
}
};
int main() {
Bar b = 7;
b = 7;
return 0;
}
输出为:
code path A
code path B
感觉等号的存在掩盖了差异。 即使它是"常识",我也喜欢使初始化看起来与赋值明显不同,因为我们能够这样做。
这只是初始化某物的语法:-
SomeClass data(12, 134);
这看起来很合理,但是
int data(123);
看起来很奇怪,但它们是相同的语法。