C++ Trivial Stuff

1.左值与右值

In concept (though not always in practice), rvalues correspond to temporary objects returned from functions, while lvalues correspond to objects you can refer to, either by name or by following a pointer or lvalue reference.

确定表达式是左值还是右值的方式是看是否可以获取到表达式的地址,如果可以就是左值,否则就是右值。表达式是左值还是右值跟表达式本身的类型是独立的。
例如,当一个parameter是右值引用的时候parameter本身是左值。

class Widget {
public:
	Widget(Widget&& rhs); // rhs是左值,虽然它的类型是右值引用
	// ...
};

在上述代码中,在移动构造函数Widget(Widget&& rhs);内部是可以获取rhs的地址的,因此rhs是左值,即使它的类型是右值引用。基于类似的原因,所有的parameter都是左值。【注:本文中形参和实参分别用parameter和argument表示。parameter一定是左值,argument可以是左值或右值】。

2.声明和定义

声明declaration是告诉编译器某个东西的名称和类型(type),但略去细节。
定义definition的任务是提供编译器一些声明中所遗漏的细节。

ellipse
图1 declaration & definition

3.尽量以const,enum,inline替换#define

  • 对于单纯常量,最好以const对象或enums替换#define
  • 对于形似函数的宏(macros),最好改用inline替换#define
// 以a和b的较大值调用f函数
#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a):(b))

应当改成如下形式:

template<typename T>
inline void callWithMax(const T& a, const T& b) // 由于不知道T是什么,因此采用pass by reference-to-const
{
    f(a>b?a:b);
}

4.typename后加{}产生临时对象

test_new.h

#ifndef TEST_NEW_H_
#define TEST_NEW_H_

#include <iostream>

namespace test_new
{
    extern const int bufSize;

    struct Source_reference
    {
        char const* filename;
        int line_number;
    };
	
    /* typename后加{}产生临时对象(一般会调用构造函数),但不调用构造函数 */
#define SOURCE_REF Source_reference{__FILE__, __LINE__}
    
	auto main() -> int;
}
#endif

test_new.cpp

#include "test_new.h"

#include <iostream>
#include <vector>

namespace test_new
{
    const int bufSize = 456;
    
    auto main() -> int
    {
        std::cout << "testing test_new......" << std::endl;

        auto sth = SOURCE_REF;
        std::cout << sth.filename << ", " << sth.line_number << std::endl;
        
        Source_reference sr = Source_reference{__FILE__, __LINE__};
        std::cout << sr.filename << ", " << sr.line_number << std::endl;

		std::cout << "test_new pass" << std::endl;
		std::cout << "------------------------------" << std::endl;
        
        return 0;
    }
}

main.cpp

#include "test_new.h"

#include <string>
#include <iostream>

int main()
{
    std::cout << "__cplusplus: " << __cplusplus << std::endl;

    test_new::main();
    std::cout << "test_new::bufSize = " << test_new::bufSize << std::endl;

    std::cout << "The end." << std::endl;
}

输出:

__cplusplus: 199711
testing test_new......
D:\00.testcodes\code\test_new.cpp, 19
D:\00.testcodes\code\test_new.cpp, 22
test_new pass
------------------------------
test_new::bufSize = 456
The end.

5.new typenamenew typename()的区别

new typename产生的对象其值(或其成员的值)是未初始化的;而new typename()产生的对象其值(或其成员的值)是初始化为0(或NULLnullptr)的。不管是结构体还是基础类型都是如此。

    int *pa = new int;       // *pa的值可能是-842150451
    int *pb = new int();     // *pb的值是0

6. POD( Plain Old Data)

简单理解能进行memcpy的类型(基础类型、结构体、类)就是POD类型。

#include <iostream>
#include <type_traits>

namespace test_pod
{
    struct A{private: int i;};
    class B: public A{};
    struct C : private B {void print(){std::cout << "struct C" << std::endl;}};
    struct D : protected C {};
    // 有构造函数,析构函数就不是POD
    struct E : D {~E(){std::cout << "E's dtor called." << std::endl;}};
    // 成员有初值也不是POD
    struct F{int i = 0;};

    auto main() -> int {
        std::cout << "testing test pod......\n" << std::endl;
        std::cout << std::boolalpha;
        std::cout << "int: " << std::is_pod<int>::value << std::endl;
        std::cout << "A: "  << std::is_pod<A>() << std::endl;
        std::cout << "B: "  << std::is_pod<B>() << std::endl;
        std::cout << "C: "  << std::is_pod<C>() << std::endl;
        std::cout << "D: "  << std::is_pod<D>::value << std::endl;
        std::cout << "E: "  << std::is_pod<E>::value << std::endl;
        std::cout << "F: "  << std::is_pod<F>::value << std::endl;

		std::cout << "------------------------------" << std::endl;

        return 0;
    }
}

输出:

testing test pod......

int: true
A: true
B: true
C: true
D: true
E: false
F: false
------------------------------

Reference

[1]. Scott Meyers. Effective Modern C++. O’Reilly, November 2014: First Edition.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值