c ++变量赋值,这是正常的方式..?

时间:2012-09-05 15:41:13

标签: c++ variables styles variable-assignment

这可能是一个愚蠢的问题,但我仍然有点好奇...... 最近我在做一个以前的同事项目,我注意到他真的喜欢用这样的东西:

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;
};

8 个答案:

答案 0 :(得分:8)

对于基本类型,没有区别。使用与现有代码一致的内容,看起来更自然。

否则,

A a(x);

执行直接初始化

A a = x;

执行复制初始化

第二部分是成员初始化列表,在StackOverflow上有一堆Q&关于它。

答案 1 :(得分:3)

两者都有效。对于内置类型,他们做同样的事情;对于班级类型有一个微妙的区别。

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)

答案 2 :(得分:3)

以上所有答案都是正确的。只需添加它,C ++ 11支持另一种方式,就像他们所说的初始化变量一样。

int a = {2} ;

int a {2} ;

答案 3 :(得分:2)

这是一种初始化变量的C ++风格--C ++为基本类型添加了它,因此相同的形式可用于基本和用户定义的类型。这对于那些打算为任何一种类型实例化的模板代码都非常重要。

您是否希望将它用于基本类型的正常初始化是样式首选项。

请注意,C ++ 11还添加了uniform initialization syntax,它允许所有类型使用相同的初始化样式 - 甚至是POD结构和数组之类的聚合(尽管用户定义的类型可能需要具有新类型采用初始化列表以允许统一语法与它们一起使用的构造函数。)

答案 4 :(得分:2)

其他一些好的答案指出了构建“就地”(ClassType v(<constructor args>))和创建临时对象以及使用复制构造函数复制它(ClassType v = <constructor arg>)之间的区别。我想还需要补充两点。首先,第二种形式显然只有一个参数,所以如果你的构造函数需要多个参数,你应该更喜欢第一种形式(是的,有很多方法,但我认为直接构造更简洁和可读 - 但是正如已经指出的那样,这是个人的优先权。)

其次,如果您的复制构造函数与标准构造函数有很大不同,那么您使用的表单很重要。在大多数情况下情况并非如此,有些人会认为这样做是个坏主意,但语言确实允许这种情况(因为它,你最终会遇到的所有惊喜,但是,是你自己的错。)

答案 5 :(得分:2)

你的问题根本不是一个愚蠢的问题,因为事情并不像看起来那么简单。假设你有:

class A {
  public:
    A() {}
};

class B {
  public:
    class B(A const &) {}
};

书写

B b = B(A());

要求可以访问B的复制构造函数。写

B b = A();

还要求B的转换构造函数B(A const&amp;)不要声明为显式。另一方面,如果你写

A a;
B b(a);

一切都很好,但是如果你写的话

B b(A());

这被编译器解释为函数b的声明,该函数采用无名参数,该参数是返回A的无参数函数,导致神秘的错误。这称为C++'s most vexing parse

答案 6 :(得分:2)

我更喜欢使用括号样式...虽然我总是使用空格来区分函数或方法调用,我不使用空格:

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

感觉就像等号的存在掩盖了差异。即使它是“常识”,我也希望初始化看起来与赋值明显不同,因为我们能够这样做。

答案 7 :(得分:1)

它只是初始化某些内容的语法: -

SomeClass data(12, 134);

这看起来很合理,但

int data(123);

看起来很奇怪,但它们的语法相同。