C+的隐藏特征+;? 当问题的“隐藏特征”出现时,没有C++的爱?我想我会把它扔出去。C++的一些隐藏特性是什么?

C+的隐藏特征+;? 当问题的“隐藏特征”出现时,没有C++的爱?我想我会把它扔出去。C++的一些隐藏特性是什么?,c++,hidden-features,C++,Hidden Features,C++是一个标准,不应该有任何隐藏的功能 C++是一种多范例语言,你可以把最后的钱押在隐藏的特性上。许多例子中有一个是:。标准委员会中没有人打算在编译时执行图灵完全子语言。绑定到常量引用的临时变量的生存期是很少有人知道的。或者至少是我最喜欢的C++知识,大多数人都不知道。 const MyClass& x = MyClass(); // temporary exists as long as x is in scope 数组运算符是关联的 [8]是*(A+8)的同义词。因为加法是关联的

C++是一个标准,不应该有任何隐藏的功能


C++是一种多范例语言,你可以把最后的钱押在隐藏的特性上。许多例子中有一个是:。标准委员会中没有人打算在编译时执行图灵完全子语言。

绑定到常量引用的临时变量的生存期是很少有人知道的。或者至少是我最喜欢的C++知识,大多数人都不知道。
const MyClass& x = MyClass(); // temporary exists as long as x is in scope

数组运算符是关联的

[8]是*(A+8)的同义词。因为加法是关联的,所以可以重写为*(8+A),它是…..的同义词。。。。。8[甲]


你没说有用…:-)

> P>我同意大多数帖子:C++是一种多范例语言,所以你会发现的“隐藏”特性(除了“不确定的行为”,你应该避免所有的代价)都是对设备的巧妙使用。

这些设施中的大多数不是语言的内置功能,而是基于库的功能

最重要的是<> ReII<强>,这是C++多年来C++开发人员经常忽略的。strong>运算符重载通常是一个被误解的功能,它支持类似数组的行为(下标运算符)、类似指针的操作(智能指针)和内置类似操作(乘法矩阵)

使用异常通常很困难,但通过一些工作,可以通过异常安全规范生成真正健壮的代码(包括不会失败的代码,或具有类似提交的功能的代码,这些功能将成功,或恢复到其原始状态)

< > C++中最著名的“隐藏”特性是<>强>模板元编程,因为它使您可以在编译时(而不是完全运行)中部分地(或完全)执行程序。但是这很难,并且在尝试之前必须对模板有一个坚实的理解。 另一些则利用多重范式在C++的祖先(即C)之外产生“编程方式”

使用<强>函式< /强>,可以模拟函数,附加类型安全,状态良好。使用<强>命令< /强>模式,可以延迟代码执行。大多数其他“强>设计模式< /强>可以在C++中轻松高效地实现,以生成不应该在内部的可选编码风格。“官方C++范式”列表

通过使用<强>模板,可以生成对大多数类型都适用的代码,包括最初的一个,也可以增加类型安全性(如自动类型化的MalC/ReAlOc/Free)。C++对象特性非常强大(因此,如果不小心使用,则是危险的),但即使是动态多态性也有其C++的静态版本:CRTP

我发现了Scott Meyers的最有效的“C++ C++”或“特殊的C++”类型的书,从草本萨特到容易阅读的书籍,以及关于C++的已知和不太著名的特征的信息宝藏。

我喜欢的是一个使任何java程序员的头发都从恐怖中升起的:在C++中,<>强>最不为对象的方式将一个特征添加到一个对象中是通过非成员非朋友函数,而不是成员函数<强>(即类方法),因为:

    C++中,一个类的接口既是它的成员函数,也是同一个命名空间

    中的非成员函数
  • 非友元非成员函数没有访问类内部的特权。因此,在非成员非友元函数上使用成员函数将削弱类的封装

即使是有经验的开发人员也会感到惊讶


(来源:赫伯·萨特(Herb Sutter)的《本周在线大师》(84:)

ooh,我可以列出一份宠物仇恨清单:


  • 如果要以多态方式使用析构函数,则析构函数必须是虚拟的
  • 有时成员是默认初始化的,有时不是
  • 本地类别不能用作模板参数(使其不太有用)
  • 异常说明符:看起来很有用,但不是
  • 函数重载隐藏具有不同签名的基类函数
  • 在国际化方面没有有用的标准化(可移植的标准宽字符集,有人吗?我们必须等到C++0x)
有利的一面

  • 隐藏功能:函数try块。不幸的是,我还没有找到它的用途。是的,我知道他们为什么要添加它,但你必须在构造函数中重新引用它,这使得它毫无意义
  • 值得仔细研究一下STL对容器修改后迭代器有效性的保证,它可以让您创建一些稍微好一点的循环
  • Boost-这几乎不是秘密,但值得使用
  • 返回值优化(不明显,但标准特别允许)
  • 函子又名函数对象又名运算符()。这在STL中被广泛使用。这并不是什么秘密,但却是运算符重载和模板的一个很好的副作用

一个我认为有点隐藏的语言特征,因为我在学校的整个时间里都没有听说过它,它是命名空间别名。直到我在Boost文档中遇到了它的例子,它才引起我的注意。当然,现在我知道了,你可以在任何标准的C++引用中找到它。

namespace fs = boost::filesystem;

fs::path myPath( strPath, fs::native );

可以将URI放入C++源,无错误。例如:

void foo() {
    http://stackoverflow.com/
    int bar = 4;

    ...
}
struct Bar {
  void modify() {}
}
int main (void) {
  Bar().modify();   /* non-const function invoked on a temporary. */
}
void foo (int) {}
void foo (double) {}
struct X {
  X (double d = 0.0) {}
};
void foo (X) {} 

int main(void) {
  int i = 1;
  foo(i ? 0 : 0.0); // calls foo(double)
  X x;
  foo(i ? 0.0 : x);  // calls foo(X)
}

摆脱转发声明:

struct global
{
     void main()
     {
           a = 1;
           b();
     }
     int a;
     void b(){}
}
singleton;
// void (*f)(); // same
id<void()>::type *f;

// void (*f(void(*p)()))(int); // same
id<void(int)>::type *f(id<void()>::type *p);

// int (*p)[2] = new int[10][2]; // same
id<int[2]>::type *p = new int[10][2];

// void (C::*p)(int) = 0; // same
id<void(int)>::type C::*p = 0;
使用?:运算符写入开关语句:

string result = 
    a==0 ? "zero" :
    a==1 ? "one" :
    a==2 ? "two" :
    0;
在一条线上做所有事情:

void a();
int b();
float c = (a(),b(),1.0f);
不带memset的结构归零:

FStruct s = {0};
正火/包角-和ti
struct Bar {
  void modify() {}
}
int main (void) {
  Bar().modify();   /* non-const function invoked on a temporary. */
}
void foo (int) {}
void foo (double) {}
struct X {
  X (double d = 0.0) {}
};
void foo (X) {} 

int main(void) {
  int i = 1;
  foo(i ? 0 : 0.0); // calls foo(double)
  X x;
  foo(i ? 0.0 : x);  // calls foo(X)
}
class clName
{
  clName();
  int a[10];
};
clName::clName() : a()
{
}
map<int, string> m;
string& s = m[42]; // no need for map::find()
if (s.empty()) { // assuming we never store empty values in m
  s.assign(...);
}
cout << s;
x = (y < 0) ? 10 : 20;
(a == 0 ? a : b) = 1;
if (a == 0)
    a = 1;
else
    b = 1;
 vector<string> V;
 copy(istream_iterator<string>(cin), istream_iterator<string>(),
     back_inserter(V));
if(int * p = getPointer()) {
    // do something
}
struct MutexLocker { 
    MutexLocker(Mutex&);
    ~MutexLocker(); 
    operator bool() const { return false; } 
private:
    Mutex &m;
};

#define locked(mutex) if(MutexLocker const& lock = MutexLocker(mutex)) {} else 

void someCriticalPath() {
    locked(myLocker) { /* ... */ }
}
switch(int value = getIt()) {
    // ...
}
while(SomeThing t = getSomeThing()) {
    // ...
}
SomeType t = u;
SomeType t(u);
SomeType t();
SomeType t;
SomeType t(SomeType(u));
template<typename From, typename To>
union union_cast {
    From from;
    To   to;

    union_cast(From from)
        :from(from) { }

    To getTo() const { return to; }
};
template <typename T> 
class Creator { 
    friend void appear() {  // a new function ::appear(), but it doesn't 
        …                   // exist until Creator is instantiated 
    } 
};
Creator<void> miracle;  // ::appear() is created at this point 
Creator<double> oops;   // ERROR: ::appear() is created a second time! 
template <typename T> 
class Creator { 
    friend void feed(Creator<T>*){  // every T generates a different 
        …                           // function ::feed() 
    } 
}; 

Creator<void> one;     // generates ::feed(Creator<void>*) 
Creator<double> two;   // generates ::feed(Creator<double>*) 
for(struct { int a; float b; } loop = { 1, 2 }; ...; ...) {
    ...
}
struct A {
protected:
    int a;
};

struct B : A {
    // error: can't access protected member
    static int get(A &x) { return x.a; }
};

struct C : A { };
void f(std::stack<int> &s) {
    // now, let's decide to mess with that stack!
    struct pillager : std::stack<int> {
        static std::deque<int> &get(std::stack<int> &s) {
            // error: stack<int>::c is protected
            return s.c;
        }
    };

    // haha, now let's inspect the stack's middle elements!
    std::deque<int> &d = pillager::get(s);
}
struct A {
protected:
    int a;
};

struct B : A {
    // valid: *can* access protected member
    static int get(A &x) { return x.*(&B::a); }
};

struct C : A { };
void f(std::stack<int> &s) {
    // now, let's decide to mess with that stack!
    struct pillager : std::stack<int> {
        static std::deque<int> &get(std::stack<int> &s) {
            return s.*(pillager::c);
        }
    };

    // haha, now let's inspect the stack's middle elements!
    std::deque<int> &d = pillager::get(s);
}
void f(std::stack<int> &s) {
    // now, let's decide to mess with that stack!
    struct pillager : std::stack<int> {
        using std::stack<int>::c;
    };

    // haha, now let's inspect the stack's middle elements!
    std::deque<int> &d = s.*(&pillager::c);
}
// void (*f)(); // same
id<void()>::type *f;

// void (*f(void(*p)()))(int); // same
id<void(int)>::type *f(id<void()>::type *p);

// int (*p)[2] = new int[10][2]; // same
id<int[2]>::type *p = new int[10][2];

// void (C::*p)(int) = 0; // same
id<void(int)>::type C::*p = 0;
// boost::identity is pretty much the same
template<typename T> 
struct id { typedef T type; };
template <size_t X, size_t Y>
struct bitfield
{
    char left  : X;
    char right : Y;
};
void f() { }
void g() { return f(); }
void f() { return (void)"i'm discarded"; }
template<typename T>
struct sample {
  // assume f<T> may return void
  T dosomething() { return f<T>(); }

  // better than T t = f<T>(); /* ... */ return t; !
};
for(T i, j; can_continue(i, j); ++i, void(), ++j)
  do_code(i, j);
i = a > b ? a : throw something();
void foo()
{
  return throw something();
}
template<typename Func1, typename Func2>
class callable {
  Func1 *m_f1;
  Func2 *m_f2;

public:
  callable(Func1 *f1, Func2 *f2):m_f1(f1), m_f2(f2) { }
  operator Func1*() { return m_f1; }
  operator Func2*() { return m_f2; }
};

void foo(int i) { std::cout << "foo: " << i << std::endl; }
void bar(long il) { std::cout << "bar: " << il << std::endl; }

int main() {
  callable<void(int), void(long)> c(foo, bar);
  c(42); // calls foo
  c(42L); // calls bar
}
+AnEnumeratorValue
struct Foo {
  static int const value = 42;
};

// This does something interesting...
template<typename T>
void f(T const&);

int main() {
  // fails to link - tries to get the address of "Foo::value"!
  f(Foo::value);

  // works - pass a temporary value
  f(+Foo::value);
}
// This does something interesting...
template<typename T>
void f(T const& a, T const& b);

int main() {
  int a[2];
  int b[3];
  f(a, b); // won't work! different values for "T"!
  f(+a, +b); // works! T is "int*" both time
}
struct A { void f() { } };

struct B : virtual A { void f() { cout << "B!"; } };
struct C : virtual A { };

// name-lookup sees B::f and A::f, but B::f dominates over A::f !
struct D : B, C { void g() { f(); } };