一、根据C++11标准,以下程序输出什么?
#include <iostream> using namespace std; class A { public: A() { cout << "A"; } A(const A &) { cout << "a"; } }; class B : virtual A { public: B() { cout << "B"; } B(const B &) { cout << "b"; } }; class C : virtual A { public: C() { cout << "C"; } C(const C &) { cout << "c"; } }; class D :B, C { public: D() { cout << "D"; } D(const D &) { cout << "d"; } }; int main() { D d1; D d2(d1); }
答案: ABCDABCd
解析: main()函数的第一行,d1被初始化。此时虚基类A的构造函数最先执行,之后B,C,按D的继承顺序从左到右依次调用B的构造函数,C的构造函数,最后才调用D自己的构造函数。
main()函数的第二行,d2被初始化。此时因为D类显示定义了拷贝构造函数,所以d2不会去调用父类的拷贝构造函数,所以答案为ABCd。
二、根据C++11的新标准,以下程序输出什么?
答案: 112212#include <iostream> #include <utility> int y(int &) { return 1; } int y(int &&) { return 2; } template <class T> int f(T &&x) { return y(x); } template <class T> int g(T &&x) { return y(std::move(x)); } template <class T> int h(T &&x) { return y(std::forward<T>(x)); } int main() { int i = 10; std::cout << f(i) << f(20); std::cout << g(i) << g(20); std::cout << h(i) << h(20); return 0; }
解析: 首先要明确一点,T&&在模板函数中并不一定是右值引用,它取决于实例化它的类型。如果用一个左值实例化,那个它会成为一个左值,如果用一个右值实例化变量,那么它会是一个右值。而对于x来说,不管他是左值还是右值,在函数内都是左值,所以main()函数的第一行输出11,move函数返回变量的右值,所以第二行输出22,forward函数保持变量的原来类型,所以第三行输出12.
三、根据C++11的新标准,以下程序输出什么?
#include <iostream> int main() { int a = 10; int b = 20; int x; x = (a, b); std::cout << x; }
答案:20解析:逗号运算符的运算顺序,根据C++的标准来说,逗号运算符的evaluate顺序是从左往右,每遇到一个逗号运算符,就把之前evaluate的那个变量discard。所以最后的答案为b,即20。
四、根据C++11的新标准,字符串字面值是一个const char型数组,虽然现在有些编译器支持字符串字面值付给char*,但是这样是不符合C++11的标准的,这就类似于我们定义了一个const int i,然后用int指针去指向i的地址,然而这样是未定义行为。但是有些对于字符串来说,有些编译器却支持,这不太合理。
五、根据C++11新标准,一下程序输出什么?
#include <iostream> struct GeneralException { virtual void print() { std::cout << "G"; } }; struct SpecialException : public GeneralException { void print() override { std::cout << "S"; } }; void f() { throw SpecialException(); } int main() { try { f(); } catch (GeneralException e) { e.print(); } }
答案:G
解析:SpecialException派生于基类GeneralException,main函数里跑出了一个SpecialException异常,被值捕获,所以e的动态类型为基类,如果把e改为引用类型,那么将是引用捕获,此时e的动态类型为派生类。