C & C++ Notes

Talk is cheap. Show me your achievements.

Tips:

C++ 简介 | Intro

C++ (pronounced as cee plus plus, /ˈsiː plʌs plʌs/) is a general-purpose programming language. It has imperative, object-oriented and generic programming features, while also providing facilities for low-level memory manipulation.

在 37 年前 (1979 年),一名刚获得博士学位的研究员,为了开发一个软件项目发明了一门新编程语言,该研究员名为 Bjarne Stroustrup,该门语言则命名为——C with classes,四年后改称为 C++。C++ 是一门通用编程语言,支持多种编程范式,包括过程式、面向对象 (object-oriented programming, OP)、泛型 (generic programming, GP),后来为泛型而设计的模版,被发现及证明是图灵完备的,因此使 C++ 亦可支持模版元编程范式 (template metaprogramming, TMP)。C++ 继承了 C 的特色,既为高级语言,又含低级语言功能,可同时作为系统和应用编程语言。

Bjarne Stroustrup’s Homepage.

see more @

不可以重载的操作符:

Operator Symbol
Scope resolution operator ::
Conditional operator ?:
dot operator .
Member selection operator .*
“sizeof” operator sizeof
“typeid” operator typeid

more at Operators in C and C++ - Wikipedia, the free encyclopedia.

一定要到 cppreference.com 多看看,上面有函数说明,有 demo 代码,还有 Possible implementation 什么的!简直了。

oj utils,一些面试中用得到的模板程序 @

我主要用来本地添加测试用例。

std::string trim( std::string s )
{
    if ( s.empty() ) {
        return s;
    }

    s.erase( 0, s.find_first_not_of(" ") );
    s.erase( s.find_last_not_of(" ") + 1 );
    return s;
}

void split( const std::string s,
            const std::string &delim,
            std::vector< std::string > &ret )
{
    size_t last = 0;
    size_t index = s.find_first_of( delim, last );
    while ( index != std::string::npos ) {
        ret.push_back( s.substr(last,index-last) );
        last = index + delim.size();
        index = s.find_first_of( delim, last );
    }
    if ( index-last>0 ) {
        ret.push_back( s.substr(last,index-last) );
    }
}

void line2vec( const std::string &s, std::vector< std::string > &ret )
{
    size_t left, right;
    left = s.find_first_of( std::string("[["), 0 );
    if ( left == std::string::npos ) {
        return;
    }

    left  = s.find_first_of( std::string("["), left+1 );
    right = s.find_first_of( std::string("]"), left );
    while ( left != std::string::npos && right != std::string::npos ) {
        std::string p = s.substr( left+1, right-left-1 );
        ret.push_back( p );
        left  = s.find_first_of( std::string("["), right );
        right = s.find_first_of( std::string("]"), left  );
    }
}

void str2ints( const std::string &s, std::vector<int> &ret )
{
    int i;
    if ( 1 != sscanf(s.c_str(), "%d", &i) ) {
        return;
    }
    ret.push_back(i);

    size_t left;
    left = s.find_first_of( std::string(","), 0 );
    while( left != std::string::npos ) {
        if ( 1 == sscanf(s.substr(left).c_str(), "%*c%d", &i) ) {
            ret.push_back(i);
        }
        left = s.find_first_of(std::string(","), left+1);
    }
}

refs and see also

C/C++ 拾遗 | Pearls

快问快答 | FAQ

关键概念 | Concepts

好书/博共享 | Selected Books/Posts

杂七杂八

c++里如何理解vector是动态数组,而这个单词本义是向量?为什么这么叫? - 知乎

比如想当然地把 C 里的类似知识代入 C++,结果写出有问题代码的:

int *p = new int; if (p == nullptr) { // 错误处理 }

实际上永远不可能到达错误处理,因为 new 失败不返回 nullptr,而是抛异常。


析构函数是特别的成员函数,行为和一般成员函数不一样。

问题中谈到一般成员函数需要有相同的签名(除返回类型),这是因为一个类可能有多个虚函数,需以此规则去匹配类层次架构中哪些是同一组虚函数。而每个类只能有一个析构函数,匹配不成问题。

如果定义C++语法时,析构函数不是命名为className(),而是选择所有类都相同的名字,如(),应该也不会造成问题。

refs and see also

std::vector::emplace_back - cppreference.com
template< class... Args >                           (since C++11)
void emplace_back( Args&&... args );
template< class... Args >                           (until C++17)
reference emplace_back( Args&&... args );
        (since C++17)

Appends a new element to the end of the container. The element is constructed through std::allocator_traits::construct, which typically uses placement-new to construct the element in-place at the location provided by the container. The arguments args... are forwarded to the constructor as std::forward<Args>(args)....

If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.

The following code uses emplace_back to append an object of type President to a std::vector. It demonstrates how emplace_back forwards parameters to the President constructor and shows how using emplace_back avoids the extra copy or move operation required when using push_back.

emplace_back avoids the extra copy or move operation required when using push_back.

#include <vector>
#include <string>
#include <iostream>

struct President
{
    std::string name;
    std::string country;
    int year;

    President(std::string p_name, std::string p_country, int p_year)
        : name(std::move(p_name)), country(std::move(p_country)), year(p_year)
    {
        std::cout << "I am being constructed.\n";
    }
    President(President&& other)
        : name(std::move(other.name)), country(std::move(other.country)), year(other.year)
    {
        std::cout << "I am being moved.\n";
    }
    President& operator=(const President& other) = default;
};

int main()
{
    std::vector<President> elections;
    std::cout << "emplace_back:\n";
    elections.emplace_back("Nelson Mandela", "South Africa", 1994);

    std::vector<President> reElections;
    std::cout << "\npush_back:\n";
    reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));

    std::cout << "\nContents:\n";
    for (President const& president: elections) {
        std::cout << president.name << " was elected president of "
                  << president.country << " in " << president.year << ".\n";
    }
    for (President const& president: reElections) {
        std::cout << president.name << " was re-elected president of "
                  << president.country << " in " << president.year << ".\n";
    }
}
emplace_back:
I am being constructed.

push_back:
I am being constructed.
I am being moved.

Contents:
Nelson Mandela was elected president of South Africa in 1994.
Franklin Delano Roosevelt was re-elected president of the USA in 1936.
std::make_pair - cppreference.com @
Defined in header <utility>

template< class T1, class T2 >                      (until C++11)
std::pair<T1,T2> make_pair( T1 t, T2 u );
template< class T1, class T2 >                      (since C++11)
std::pair<V1,V2> make_pair( T1&& t, T2&& u );
template< class T1, class T2 >                      (until C++14)
constexpr std::pair<V1,V2> make_pair( T1&& t, T2&& u );

Creates a std::pair object, deducing the target type from the types of arguments.

The deduced types V1 and V2 are std::decay<T1>::type and std::decay<T2>::type (the usual type transformations applied to arguments of functions passed by value) unless application of std::decay results in std::reference_wrapper<X> for some type X, in which case the deduced type is X&.

refs and see also

<>读书笔记(三) - zyfforlinux - 博客频道 - CSDN.NET

如何在一个月内提高 C++ 水平? - 知乎 @

“哦!原来你说的是 Two phase name look up mechanism 啊!(停顿)对于这个 Question,虽然 C++ 11(读作“伊来闻”,不读“屎遗”,下同) standard 在 Draft N3028(读作“瑟添臀添诶特”,不读“散蛋阿爸”,下同)时就已经 final decision 了, C++17 上对于 Chapter 14,section 3.3.1 条款 5,7,15 上做了进一步调整,但是迄今为止各家 compiler vendor 的 implementation 仍然 slighty difference。所以可能我们在不同的 Compiler 上都是对的。我的答案是在 IBM XL C++ 13 上获得的,Linux Z(重音) System on Power 8,not MSVC on Windows x64(读作“埃克斯碎克死天佛”,不能读“插牛屎”),you know。(停顿)Our experience 可能不太一样。我刚刚仔细的考虑过你的 Result,应该是 Make Sense 的。关于这个问题的进一步讨论,我想我们可以参考一下 TCPL 的 275 页(随便报个页数就可以了,没人会真去查的)。”

注意,一定要用英语,一定要自信。说中文就说不知道,没看过。99.99%的面试官不敢说自己没听懂。

所以总结一下,面试的时候你怎么样并不要紧,你只需要做到以下几点中的任意一条:

  1. 让面试官觉得你懂
  2. 和面试官的答案相同
  3. 让面试官觉得他也不懂

这样就是一个成功的面试了。

  至于你说进去以后怎么办,南郭先生的故事听过吗。
  如果大家都牛逼,也就没人在乎你是不是屎。
  如果大家都不牛逼,那一坨屎从道德上就不能嫌弃其他屎。
  如果乐团拆分了,记住,不要去当乐手了,要提前转型,当乐团老板吧。