C ++标准中最令人惊讶的元素是什么?

时间:2009-10-31 23:54:46

标签: c++

我决定更熟悉我最喜欢的编程语言,但只读 阅读标准很无聊。

C ++中最令人惊讶,反直觉,或者只是简单的奇怪元素是什么?令你震惊的是你跑到最近的编译器检查它是否真的存在?

我会接受第一个答案,即使 我已经测试过它,我也不会相信。 :)

7 个答案:

答案 0 :(得分:10)

我发现它有点令人惊讶

class aclass
{
public:
int a;
};

some_function(aclass());

a初始化为0中的some_function,而

aclass ac;
some_function(ac);

将保留单位资本。 如果明确定义aclass的默认构造函数:

class aclass
{
public:
aclass(): a() {}
int a;
};

然后 aclass ac; 还会将a初始化为0

答案 1 :(得分:9)

我可以添加的另一个答案是throw()限定符。例如:

void dosomething() throw()
{
   // ....
}

void doSomethingElse() throw(std::exception)
{
  // ....
}

直观地说,这看起来像是与编译器的契约,表明除了列出的那些之外,不允许此函数抛出任何异常。但实际上,这在编译时没有任何作用。相反,它是一个运行时机制,它不会阻止该函数实际抛出异常。更糟糕的是,如果抛出未列出的异常,它会通过调用std::terminate()来终止您的应用程序。

答案 2 :(得分:8)

几个声明者的顺序实际上是无序的:

volatile long int const long extern unsigned x;

相同
extern const volatile unsigned long long int x;

答案 3 :(得分:5)

考虑到C ++通常是多么无情,我发现标准实际上允许你delete空指针有点令人惊讶。

答案 4 :(得分:2)

对象在构造期间更改类型。

特别是,当从构造函数调用虚函数时,将调用最派生的覆盖。而是从正在当前构建的类调用实现。如果该实现恰好是0(纯虚函数),则程序将在运行时崩溃。

一个半现实世界的例子:

class AbstractBase {
  public:
    AbstractBase() {
      log << "Creating " << className() << endl;
    }
  protected:
    virtual string className() const = 0;
}

class ConcreteGuy {
  protected:
    virtual string className() const { return "ConcreteGuy"; }
}

构造ConcreteGuy对象后,程序将以“调用纯虚函数”错误消息终止。

这就是为什么从构造函数调用虚函数被认为是邪恶的。

答案 5 :(得分:0)

众所周知,数组启动器可能像枚举定义一样跳转索引。

// initializing an array of int
int a[ 7] = { [5]=1, [2]=3, 2};
// resulting in
int a[ 7] = { 0, 0, 3, 2, 0, 1, 0};

// initializing an array of struct
struct { int x,y; } ar[ 4] = { [1].x=23, [3].y=34, [1].y=-1, [1].x=12};
// resulting in
struct { int x,y; } ar[ 4] = { { 0, 0}, { 12, -1}, { 0, 0}, { 0, 34}};

// interesting usage
char forbidden[ 256] = { ['a']=1, ['e']=1, ['i']=1, ['o']=1, ['u']=1};

大多数these也适用于C ++。

答案 6 :(得分:0)

在C ++语句中评估某事......

int main()
{
    "This is a valid C++ program!"
    "I will list the first five primes:";
    2;
    3;
    5;
    7;
    11;
}