为什么使用=来初始化的一个基本类型在C++?
-
20-08-2019 - |
题
我工作的地方,人们主要认为,对象是最好的初始化使用C++style建设(与括号中),而原始的类型应该被初始化与=操作员:
std::string strFoo( "Foo" );
int nBar = 5;
似乎没有人能够解释为什么他们喜欢的东西这种方式,虽然。我可以看到, std::string = "Foo";
将低效率的,因为它将涉及一个额外的复制,但是,什么是错的只是驱逐的 =
操作员,总共和使用括号内的无处不在?
它是一个共同的《公约》的?什么背后的思想?
解决方案
除非你已经证明了它相对于性能的问题,我也不会在你的例子(std::string foo = "Foo";
)担心使用赋值运算符的额外拷贝。我会很惊讶,如果是副本,即使存在,一旦你看看优化的代码,我认为,实际上将调用适当的参数的构造函数。
在回答你的问题,是的,我会说,这是一个相当常见的约定。传统上,人们使用分配初始化内置类型,并没有令人信服的理由来改变传统。可读性和习惯是给它如何影响小,对最终的代码本公约完全有效的原因。
其他提示
初始化变量与=操作人员或有一个构造呼吁在语义上是相同的,它只是问题的风格。我更喜欢=操作,因为它读起来更加自然。
使用=operator 通常 不产生额外的复制-它只是电话正常的构造。然而,请注意,与非基本类型,这只是为初始化发生的同时作的声明。比较:
std::string strFooA("Foo"); // Calls std::string(const char*) constructor
std::string strFoo = "Foo"; // Calls std::string(const char*) constructor
// This is a valid (and standard) compiler optimization.
std::string strFoo; // Calls std::string() default constructor
strFoo = "Foo"; // Calls std::string::operator = (const char*)
当你有非凡的默认构造的,后者建设可以稍更多的效率低下。
的 C++标准,第8.5节,第14段指出:
否则(即剩余的副本-初始化的情况)、临时会被创建。用户定义的转换序列,可以转换从该来源类型的目标类型或派生类其是所列举的(13.3.1.4),和最好的一个选择是通过载决议(13.3).用户定义转换的所以选择的是所谓的转换的初始化表达成一个临时的,其类型为返回的类型叫的用户定义的转换功能,与cv-限定词 目的类型。如果转换不能做的或者是含糊不清,初始化是虐待形成的。对被初始化的然后直接的初始化 从临时根据本规则上。87) 在某些情况下,实施被允许消除暂时通过初始化的对象;看到12.2.
一部分,第12.2各国:
即使建立临时目的是避免的,所有的语义限制必须得到尊重,因为如果临时的目的是创建。[例如:即使复制的构造就是不叫,所有的语义限制,例如无障碍(11),应当得到满足。]
我只是觉得再傻litb岗位的需要。
string str1 = "foo";
被称为复制初始化,因为编译器做什么,如果它没有任何的Elid临时变量是:
string str1(string("foo"));
检查使用的转换构造是隐式的旁边。事实上,所有的隐式转换是由标准拷贝初始化的定义。据说,从U型的隐式转换到类型T是有效的,如果
T t = u; // u of type U
是有效的。
在constrast,
string str1("foo");
在做什么写,被称为直接初始化。它还可以与显式的构造。
顺便提及,可以通过使用-fno-的Elid-构造禁用临时对象的eliding:
-fno-elide-constructors
The C++ standard allows an implementation to omit creating a temporary which
is only used to initialize another object of the same type. Specifying this
option disables that optimization, and forces G++ to call the copy constructor
in all cases.
在标准说,有
之间几乎没有差别T a = u;
和
T a(u);
如果T和U的类型是原始类型。所以,你可以使用这两种形式。我认为这是只是它的风格,使人们使用第一种形式,而不是第二。
有些人可能会使用首先在某些情况下,因为他们要澄清对声明:
T u(v(a));
migh看到有人作为被使用临时类型u
其将获取它的构造称为v
的参数的初始化的变量a
的定义。但事实上,什么编译器与是这样的:
T u(v a);
它创建了一个函数声明采用类型v
的参数,并用参数调用a
。这样人们就
T u = v(a);
消除歧义,尽管他们可以做
T u((v(a)));
也是如此,因为从未有围绕功能参数括号,则编译器将读取它作为变量定义的,而不是函数声明太:)
您可能会发现这样的代码
std::string strFoo = "Foo";
将避免这样做的额外拷贝和编译为相同的代码(单参数的构造的呼叫)作为一个与括号中。
在另一方面,存在这样的情况,其中一个必须的使用括号,例如作为构造构件初始化列表。
我觉得用=或括号的构造局部变量主要是个人选择的问题。
好了,谁知道是什么的他们的思考,但我也喜欢=基本类型,主要是因为它们不是对象,因为这是“正常”的方式来初始化它们。
这是风格的问题。就连声明“的std :: string =‘富’,是低效的,因为它会涉及额外的副本”是不正确的。该“额外副本”是由编译器除去。
我相信,更多的是一种习惯,很少有对象可以使用=初始化,字符串就是其中之一。这也是做的方式,你说什么“用括号无处不在(该语言可以让你使用它)”
一个论据,人们可以作出:
的std :: string FOO( “条”);
时,它让事情即使参数计数的变化是相同的,即:
的std :: string FOO( “条”,5);
不与 '=' 符号工作。
的另一件事是,对许多对象“=”感觉不自然,例如说你有一个Array类,其中参数给出的长度:
阵列ARR = 5;
感觉并不好,因为我们不构造具有数值5的阵列,但长度为5:
阵列ARR(5);
感觉更自然,因为你正在构造的对象与给定的参数,而不是仅仅复制的值。
但后来仅仅是用来迷惑你甚至更多,你在初始化列表使用对象语法初始化元。
foo::foo()
,anInt(0)
,aFloat(0.0)
{
}