柚子快報(bào)激活碼778899分享:開發(fā)語言 C++隨筆記錄
柚子快報(bào)激活碼778899分享:開發(fā)語言 C++隨筆記錄
?C++空指針、智能指針
NULL和nullptr
#include
using namespace std;
void func(char* str) {cout << "char * version" << endl;}
// void func(int i) {cout << "int version" << endl;}
int main()
{
func(NULL);
func(nullptr);
return 0;
}
輸出:
char * version
char * version
#include
using namespace std;
// void func(char* str) {cout << "char * version" << endl;}
void func(int i) {cout << "int version" << endl;}
int main()
{
func(NULL);
// func(nullptr); // 會(huì)報(bào)錯(cuò)
return 0;
}
輸出:
int version
智能指針
unique_ptr類似于普通指針,但是會(huì)在離開作用域時(shí)自動(dòng)刪除釋放資源,unique_ptr的特點(diǎn)是內(nèi)存和資源始終被釋放,即使執(zhí)行返回語句和拋出異常,創(chuàng)建unique_ptr時(shí)使用如下語句:
auto anEmployee = make_unique
make_unique是C++14中引入的,如果不兼容C++14,可以使用如下語句創(chuàng)建:
unique_ptr
?unique_ptr可以用于存儲(chǔ)C風(fēng)格的數(shù)組,下面創(chuàng)建一個(gè)包含10個(gè)Employee實(shí)例的數(shù)組,存儲(chǔ)在unique_ptr中
auto employees = make_unique
cout << "Salary: " << employees[0].salary << endl;
要?jiǎng)?chuàng)建shared_ptr,應(yīng)當(dāng)使用std::make_shared_ptr<>();
auto anEmplyee = std::make_shared
if (anEmployee)
從C++17開始,也可以將數(shù)組存儲(chǔ)在shared_ptr中,而舊版的C++不允許這么做,但注意,此時(shí)不能使用C++17的make_shared<>()
shared_ptr
分配二維數(shù)組
char** allocateCharacterBoard(size_t xDimension, size_t yDimension) {
char** myArray = new char*[xDimension];
for (int i = 0; i < xDimension; i++) {
myArray[i] = new char[yDimension];
}
return myArray;
}
釋放多維數(shù)組
void releaseCharcterBoard(char** myArray, size_t xDimension) {
for (size_t i = 0; i < xDimension; i++) {
delete [] myArray[i];
}
delete[] myArray;
}
右值引用是左值
#include
using namespace std;
void process_value(int & i) {
std::cout << "Lvalue processed!" << i << std::endl;
}
void process_value(int && i) {
std::cout << "Rvalue processed!" << i << std::endl;
}
void forward_value(int && i) {
process_value(i);
}
int main() {
int a = 1;
process_value(a);
process_value(1);
forward_value(2);
/* 輸出結(jié)果
Lvalue processed!1
Rvalue processed!1
Lvalue processed!2
*/
return 0;
}
以string類為例,實(shí)現(xiàn)拷貝賦值和拷貝構(gòu)造
// string 類為示例,實(shí)現(xiàn)拷貝構(gòu)造函數(shù)和拷貝賦值操作符
#include
#include
#include
class MyString {
private:
char* m_data;
size_t m_len;
void init_data(const char* str) {
m_len = strlen(str);
m_data = new char[m_len+1];
memcpy(m_data, str, m_len);
m_data[m_len] = '\0';
}
public:
MyString() {
m_len = 0;
m_data = nullptr;
}
MyString(const char* str) {
init_data(str);
}
MyString(const MyString& str) {
init_data(str.m_data);
std::cout << "copy construct is called! source: " << str.m_data << std::endl;
}
MyString& operator=(const MyString& str) {
if (this != &str) {
init_data(str.m_data);
}
std::cout << "Copy Assignment is called! source: " << str.m_data << std::endl;
return *this;
}
virtual ~MyString() {
if (m_data) {
std::cout << "call destory fun~" << m_data << std::endl;
free(m_data);
}
}
};
int main() {
MyString str;
str = MyString("hello");
std::vector
vec.push_back(MyString("World"));
}
輸出:
Copy Assignment is called! source: hello
call destory fun~hello
copy construct is called! source: World
call destory fun~World
call destory fun~World
call destory fun~hello
添加移動(dòng)賦值和移動(dòng)構(gòu)造函數(shù)
// string 類為示例,實(shí)現(xiàn)拷貝構(gòu)造函數(shù)和拷貝賦值操作符
#include
#include
#include
class MyString {
private:
char* m_data;
size_t m_len;
void init_data(const char* str) {
m_len = strlen(str);
m_data = new char[m_len+1];
memcpy(m_data, str, m_len);
m_data[m_len] = '\0';
}
public:
MyString() {
m_len = 0;
m_data = nullptr;
}
MyString(const char* str) {
init_data(str);
}
MyString(const MyString& str) {
init_data(str.m_data);
std::cout << "copy construct is called! source: " << str.m_data << std::endl;
}
// 1. 參數(shù)(右值)的符號(hào)必須是右值引用符號(hào),即“&&”。
// 2. 參數(shù)(右值)不可以是常量,因?yàn)槲覀冃枰薷挠抑怠?/p>
// 3. 參數(shù)(右值)的資源鏈接和標(biāo)記必須修改。否則,右值的析構(gòu)函數(shù)就會(huì)釋放資源。轉(zhuǎn)移到新對(duì)象的資源也就無效了。
MyString(MyString&& str) {
std::cout << "Call move Constructor ! source: " << str.m_data << std::endl;
m_len = str.m_len;
m_data = str.m_data;
str.m_len = 0;
str.m_data = nullptr;
}
MyString& operator=(const MyString& str) {
if (this != &str) {
init_data(str.m_data);
}
std::cout << "Copy Assignment is called! source: " << str.m_data << std::endl;
return *this;
}
MyString& operator=(MyString&& str) {
std::cout << "Call move Constructor ! source: " << str.m_data << std::endl;
if (this != &str) {
m_len = str.m_len;
m_data = str.m_data;
str.m_len = 0;
str.m_data = nullptr;
}
return *this;
}
virtual ~MyString() {
if (m_data) {
std::cout << "call destory fun~" << m_data << std::endl;
free(m_data);
}
}
};
int main() {
MyString str;
str = MyString("hello");
std::vector
vec.push_back(MyString("World"));
}
輸出:
Call move Constructor ! source: hello
Call move Constructor ! source: World
call destory fun~World
call destory fun~hello
constexpr表達(dá)式
constexpr修飾變量時(shí),應(yīng)滿足:
如果該變量是某個(gè)類的對(duì)象,則它應(yīng)該立即被構(gòu)造,如果是基本類型,則應(yīng)該立即被賦值。
為構(gòu)造函數(shù)的參數(shù)或者賦值給該變量的值必須是字面常量,constexpr變量或者constexpr函數(shù)。
如果是使用構(gòu)造函數(shù)創(chuàng)建該變量,無論是顯示構(gòu)造或者隱式構(gòu)造,構(gòu)造函數(shù)必須滿足constexpr特性。
當(dāng)constexpr修飾函數(shù)時(shí),應(yīng)滿足:
該函數(shù)不能是虛函數(shù),return返回值應(yīng)該是字面類型的常量,該函數(shù)每個(gè)參數(shù)必須是字面類型的常量,函數(shù)體只能包含:
?1.null語句,2.[[../static_assert|static_assert]]語句。2.typedef 聲明或模板類別聲明,(但該模板別名聲明不定義類類型與枚舉類型)。3.using聲明。4.using 指導(dǎo)語句。5.只能存在唯一的return語句,并且return語句只能包含字面常量,constexpr變量或者constexpr函數(shù)。
當(dāng) constexpr 修飾類構(gòu)造函數(shù)時(shí),應(yīng)滿足:
- 構(gòu)造函數(shù)的每個(gè)參數(shù)必須是字面類型常量。
- 該類不能有虛基類。
- 構(gòu)造函數(shù)體必須滿足以下條件:
? ? 1. null 語句。
? ? 2. [[../static_assert|static_assert]] 語句。
? ? 3. typedef 聲明或 模板別名聲明(但該模板別名聲明不定義類類型與枚舉類型)。
? ? 4. using 聲明。
? ? 5. using 指導(dǎo)語句。
- 構(gòu)造函數(shù)中不能有 try-語句塊。
- 該類的每個(gè)基類和非靜態(tài)成員變量必須是初始化。
- 每一個(gè)隱式轉(zhuǎn)換必須是常量表達(dá)式。
#include
#include
// constexpr functions use recursion rather than iteration
constexpr int factorial(int n)
{
return n <= 1 ? 1 : (n * factorial(n-1));
}
// literal class
class conststr {
const char * p;
std::size_t sz;
public:
template
constexpr conststr(const char(&a)[N]) : p(a), sz(N-1) {}
// constexpr functions signal errors by throwing exceptions from operator ?:
constexpr char operator[](std::size_t n) const {
return n < sz ? p[n] : throw std::out_of_range("");
}
constexpr std::size_t size() const { return sz; }
};
constexpr std::size_t countlower(conststr s, std::size_t n = 0,
std::size_t c = 0) {
return n == s.size() ? c :
s[n] >= 'a' && s[n] <= 'z' ? countlower(s, n+1, c+1) :
countlower(s, n+1, c);
}
// output function that requires a compile-time constant, for testing
template
constN() { std::cout << n << '\n'; }
};
int main()
{
std::cout << "4! = " ;
constN
volatile int k = 8; // disallow optimization using volatile
std::cout << k << "! = " << factorial(k) << '\n'; // computed at run time
std::cout << "Number of lowercase letters in \"Hello, world!\" is ";
constN
}
輸出:
4! = 24
8! = 40320
Number of lowercase letters in "Hello, world!" is 9
宏定義中的# ## \符號(hào)
字符串化操作符(#)
#include
#include
#define exp(s) printf("test s is: %s\n", s)
#define exp1(s) printf("test s is: %s\n", #s)
#define exp2(s) #s
using namespace std;
int main() {
exp("Hello");
exp1(hello);
std::string str = exp2( bbbb );
/**
* 忽略傳入?yún)?shù)名前面和后面的空格。
*/
std::cout << str << " " << str.size() << std::endl;
std::string str2 = exp2( adfa asdfasf );
/**
* 當(dāng)傳入?yún)?shù)名間存在空格時(shí),編譯器將會(huì)自動(dòng)連接各個(gè)子字符串,
* 用每個(gè)子字符串之間以一個(gè)空格連接,忽略剩余空格。
*/
std::cout << str2 << " " << str2.size() << std::endl;
return 0;
}
輸出:
test s is: Hello
test s is: hello
bbbb 4
adfa asdfasf 12
符號(hào)連接操作符(##)
“##”是一種分隔連接方式,它的作用是先分隔,然后進(jìn)行強(qiáng)制連接。將宏定義的多個(gè)形參轉(zhuǎn)換成一個(gè)實(shí)際參數(shù)名。
注意事項(xiàng):
(1)當(dāng)用##連接形參時(shí),##前后的空格可有可無。
(2)連接后的實(shí)際參數(shù)名,必須為實(shí)際存在的參數(shù)名或是編譯器已知的宏定義。
(3)如果##后的參數(shù)本身也是一個(gè)宏的話,##會(huì)阻止這個(gè)宏的展開。
#include
#include
#define expA(s) printf("前綴加上后的字符串為:%s\n",gc_##s) //gc_s必須存在
// 注意事項(xiàng)2
#define expB(s) printf("前綴加上后的字符串為:%s\n",gc_ ## s) //gc_s必須存在
// 注意事項(xiàng)1
#define gc_hello1 "I am gc_hello1"
int main() {
// 注意事項(xiàng)1
const char * gc_hello = "I am gc_hello";
expA(hello);
expB(hello1);
}
輸出:
前綴加上后的字符串為:I am gc_hello
前綴加上后的字符串為:I am gc_hello1
計(jì)算程序運(yùn)行的時(shí)間
#include
#include
using namespace std;
using namespace std::chrono;
using ull = unsigned long long;
ull OddSum = 0;
ull EvenSum = 0;
void findEven(ull start, ull end) {
for (ull i = start; i <= end; i++) {
if ((i & 1) == 0) {
EvenSum += i;
}
}
}
void findOdd(ull start, ull end) {
for (ull i = start; i <= end; i++) {
if ((i & 1) == 1) {
OddSum += i;
}
}
}
int main() {
ull start = 0, end = 1900000000;
auto startTime = high_resolution_clock::now();
findOdd(start, end);
findEven(start, end);
auto endTime = high_resolution_clock::now();
auto duration = duration_cast
cout << "OddSum: " << OddSum << endl;
cout << "EvenSum: " << EvenSum << endl;
cout << "Sec: " << duration.count() / 1000000 << endl;
return 0;
}
輸出:
OddSum: 902500000000000000
EvenSum: 902500000950000000
Sec: 6
detach
#include
#include
#include
#include
using namespace std;
/**
* 這用于從父線程分離新創(chuàng)建的線程
* 在分離線程之前,請(qǐng)務(wù)必檢查它是否可以joinable,
* 否則可能會(huì)導(dǎo)致兩次分離,并且雙重detach()將導(dǎo)致程序終止
* 如果我們有分離的線程并且main函數(shù)正在返回,那么分離的線程執(zhí)行將被掛起
*/
void run(int count) {
while (count > 0) {
cout << count << endl;
}
std::this_thread::sleep_for(chrono::seconds(3));
}
int main() {
thread t1(run, 10);
cout << "main()" << endl;
t1.detach();
if(t1.joinable()) {
t1.detach();
}
cout << "main() after" << endl;
return 0;
}
thread id
#include
#include
using namespace std;
// 線程的通用標(biāo)識(shí)符
std::thread::id master_thread;
void do__master_thread_work() {
cout << "master" << endl;
}
void do_common_work() {
cout << "common" << endl;
}
void some_core_part_of_algorithm() {
if (std::this_thread::get_id() == master_thread) {
do__master_thread_work();
}
do_common_work();
}
int main() {
master_thread = std::this_thread::get_id();
std::cout << "master_thread: " << master_thread << endl;
std::cout << "master_thread 中運(yùn)行: " << std::endl;
some_core_part_of_algorithm();
std::cout << "thread 中運(yùn)行:" << std::endl;
thread t(some_core_part_of_algorithm);
t.join();
return 0;
}
輸出:
master_thread: 1
master_thread 中運(yùn)行:
master
common
thread 中運(yùn)行:
common
柚子快報(bào)激活碼778899分享:開發(fā)語言 C++隨筆記錄
好文推薦
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。