Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【C++】踏上C++学习之旅(十):深入“类和对象“世界,掌握编程黄金法则(五)(最终篇,内含初始化列表、静态成员、友元以及内部类等等)

【C++】踏上C++学习之旅(十):深入“类和对象“世界,掌握编程黄金法则(五)(最终篇,内含初始化列表、静态成员、友元以及内部类等等)

作者头像
埋头编程
发布于 2024-11-26 04:37:05
发布于 2024-11-26 04:37:05
19310
代码可运行
举报
文章被收录于专栏:C/C++C/C++
运行总次数:0
代码可运行

前言

本文是"类和对象"系列的最终篇,在本系列之前的文章中,给大家讲解了类和对象的六大默认成员函数,其中构造函数、析构函数、拷贝构造函数以及赋值运算符重载,这四个成员函数比较常用。另外,还讲解了C++的一个规则——“运算符重载”,正是因为有运算符重载这个玩法,使得自定义类型也能像内置类型一样能够自由使用各种运算符,但是也要注意有五个运算符是不支持重载的!

那么在本章中,我会给大家讲解类和对象初始化的一些细节,以及一个类与另一类的关系所带来的玩法!

好了,让我们开启本文知识点的探索吧!

哈哈哈
哈哈哈

1. 回看构造函数(初始化列表)

正所谓"离别三日,即更刮目相待",那接下来请大家看看构造函数还能够给我们带来哪些惊喜。

1.1 函数体内赋值

这个是我们在刚开始学习构造函数时,经常使用的一种对于对象中给成员变量赋值的写法。

用官方的话来说就是,在创建对象时,编译器通过调用构造函数,给对象中各成员变量一个合适的初始值。

比如,下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Date
{
public:
	//这种是在函数体内赋值的玩法
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};

这不禁会引发出我们心中的一些困惑:函数体内赋值的方式,能叫做对象成员变量的初始化吗?

虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。

那我们现在来捋一捋我们为什么会发出这种疑惑。

  • 初始化和赋初值的区别(只针对变量来说):初始化是变量在声明之初就给定一些值。而赋初值是指这个变量在声明之后才开始赋值。区别就在于这个变量被赋值的时候是相对于声明时还是声明后,这样的一个时间节点。

当我们了解了初始化和赋值的区别之后,我们再来看一下对象的整体初始化

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int main()
{
	//这个就是成员变量的整体初始化的地方
	Date d1(2024,11,22);

	return 0;
}

我们了解到了上述的地方是对象成员变量整体初始化的地方,那么单个成员变量初始化的地方又会在哪里呢?发明C++的本贾尼大佬,就把这个放在构造函数的一个地方,叫做"初始化列表"。

1.2 初始化列表

这里我们先讲语法:

以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Date
{
public:
	//这种是在函数体内赋值的玩法
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		,_month(month)
		,_day(day)
	{}

private:
	int _year;
	int _month;
	int _day;
};

初始化列表的语法十分的简单,但请大家书写时要注意一个地方,初始化列表只能出现在构造函数中!

1.3 初始化列表的意义

有的读者就会提出一个这样的问题,你这个初始化列表的效果和我在函数体内赋值的效果是一样的,那我以后能不能不使用初始化列表,全部成员变量我也都交给编译器自己去处理,我只管赋值这一块。

那你看看以下的场景,你没有使用初始化列表能搞得定吗?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
public:
	A(int a, char ref)
	{
		//如果不使用初始化列表初始化的话,会出现编译错误
		_a = a;
		_ref = ref;
	}
private:
	const int _a;
	char& _ref;
};

大家如果自己编译这段代码它是会报错的,原因就在于无论是const修饰的变量还是引用都有一个共同的特点,就是在变量创建之初必须初始化。那这个时候大家就能理解初始化列表的重要性了。还有一种情况也是需要初始化列表的帮助,就是当类中有一个不带默认构造函数的类对象,此时我们就显式的传递参数来初始化。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class B
{
public:
	B(int a) {}
};

class A
{
public:
	//初始化列表的语法:以冒号开头,逗号进行分割,括号的内容是成员变量该被赋值的值
	A(int a, char ref)
		:_a(a)
		,_ref(ref)
		,_b(1)
	{}
private:
	const int _a;
	char& _ref;
	B _b; //这个对象_b的构造函数是要显示传递参数的,为此只能走初始化列表
};

如果对C++比较了解的读者,此时也能明白一个问题就是,在C++11标准发布后,引入了一个成员变量能够给缺省值这样一个玩法,那这个缺省值就相当于初始化列表中那个括号里面的值,只不过这是让编译器帮我们搞定罢了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public:
	
	Date(int year = 1, int month = 1, int day = 1)
		:_year(2024)
		,_month(11)
		,_day(22)
	{}

//相当于是在初始化列表中,做了这么一件事
private:
	int _year = 2024; //给成员变量一个缺省值
	int _month = 11;
	int _day = 22;
};

当然,如果我们在初始化列表中已经有我们给变量的值了,即使在之前给了变量缺省值,编译器也会使用你在初始化列表给定的值!

1.4 初始化列表的特点

我们就来总结一下初始化列表的特点

  1. 成员变量至多只能在初始化列表中出现一次(初始化至多只能初始化一次)
  2. 类中如果包含以下成员就必须要放在初始化列表位置进行初始化:
  • const成员变量
  • 引用成员变量
  • 自定义类型对象(且该类没有默认构造函数时)

比如下面的这段代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class B
{
public:
	B(int a) {}
};

class A
{
public:
	A(int a, char ref)
		:_a(a)
		,_ref(ref)
		,_b(1)
	{}
private:
	const int _a; //const成员变量
	char& _ref;   //引用成员变量
	B _b;		  //自定义类型且没有默认的构造函数
};

这个记忆的方式也很简单,大家可以观察以下这三种类型变量的特点,在声明之初就得初始化,否则编译器会不让你用,那迫于无奈你只能选择初始化列表这条道路了。

  1. 尽量使用初始化列表进行初始化,因为不管你是是否使用初始化列表,对于自定义类型来说,一定会先使用初始化列表进行初始化
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Time
{
public:
	Time(int hour = 0)
		:_hour(hour)
	{
		cout << "Time()" << endl;
	}
private:
	int _hour;
};

class Date
{
public:
	Date(int day)
	{}
private:
	int _day;
	Time _t;
};

int main()
{
	Date d(1);

	return 0;
}

这个例子就能很好的体现这个特点,我明明没有在Date类中的初始化列表处初始化Time类的对象_t,但是成员没有报错,原因就是我们虽然没有在初始化列表写,但是编译器在编译的过程中会自动去该类中的初始化列表进行初始化工作。

  1. 成员变量在类中声明次序就是其在初始化列表中初始化顺序,与初始化列表中的向后次序无关

这个点也是很多人会忽略的一个细节,接下来让大家看看如果是错误的写法会造成什么后果!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
public:
	A(int n)
		:_a(n)
		,_b(_a)
	{
		cout << "_a:" << _a << endl;
		cout << "_b:" << _b << endl;
	}
private:
	int _b;
	int _a;
};

int main()
{
	A a(100);

	return 0;
}

大家思考一下,上面的代码打印的结果是什么?

我们来揭晓一下答案:

结果
结果

有的人可能看到这里就会犯浑,他认为是我这形参n的先是初始化了成员变量_a,此时_a的值就是100,紧接着再用_a的值去初始化成员变量_b,然后_b的值也为100。这个就是认为初始化的顺序是从_a到_b。

如果你理解了上面的初始化列表的特点4,你就很清楚的知道,初始化的顺序是从_b到_a的,所以应该先初始化_b,因为我们没有给值,编译器也不做处理,所以_b就是一个随机值。

1.5 explicit关键字

在讲这个关键字之前,我先带着大家看看一些神奇的事情

1.5.1 关于内置类型向自定义类型的隐式转换

大家看一下这段代码会不会报错:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
public:
	A(int a)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}
private:
	int _a;
};

int main()
{
	A aa = 10;
	return 0;
}

这段代码是不会报错的,大家可以先看一下结果:

结果
结果

我相信这是肯定有很多人处在很懵逼的状态,有人认为你这个10不是一个int类型的数,怎么能给一个自定义类型赋值呢,类型都不匹配肯定会报错的!

这个只是我们肉眼看到的现象,其实编译器在后面做了一些手脚,这个就是所谓的隐式转换。

怎么验证呢?大家可以看到它不仅没有报错,还调用了构造函数打印出了内容,这里我们就可以得到一点线索:

图片解析
图片解析

那此时有的人就会给出这样一个代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
public:
	A(int a, int b)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}
private:
	int _a;
	int _b;
};

int main()
{
	A aa = 10;
	return 0;
}

这个代码会报错的,因为你A中的构造函数需要传递两个参数,但是隐式类型转换的过程中只能传递一个参数。由此可见,自定义类型和内置类型的隐式类型转换是需要有一定的条件的。

条件如下:

  1. 构造函数只有一个参数
  2. 构造函数有多个参数,除第一个参数没有默认值外,其余参数都有默认值
  3. 全缺省构造函数

所以做一个总结:构造函数不仅可以构造与初始化对象,对于接收单个参数的构造函数,还具有类型转换的作用。

1.5.2 explicit关键字的作用

我们可能会遇到在某些场景中,不希望上述隐式类型转换的事情发生。那我们就要使用excplicit关键字!

explicit关键字的作用:禁止构造函数的隐式类型转换。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Date
{
public:
	// 1. 单参构造函数,没有使用explicit修饰,具有类型转换作用
	// explicit修饰构造函数,禁止类型转换---explicit去掉之后,代码可以通过编译
	explicit Date(int year)
		:_year(year)
	{}
	/*
	// 2. 虽然有多个参数,但是创建对象时后两个参数可以不传递,没有使用explicit修饰,具有类型转
   换作用
	// explicit修饰构造函数,禁止类型转换
	explicit Date(int year, int month = 1, int day = 1)
	: _year(year)
	, _month(month)
	, _day(day)
	{}
	*/
	Date& operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};

void Test()
{
	Date d1(2022);
	// 用一个整形变量给日期类型对象赋值
	// 实际编译器背后会用2023构造一个无名对象,最后用无名对象给d1对象进行赋值
	d1 = 2023;
	// 将1屏蔽掉,2放开时则编译失败,因为explicit修饰构造函数,禁止了单参构造函数类型转换的作用
}
哈哈哈
哈哈哈

2. static成员变量

2.1 概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。

这里说明一个点,就是为什么静态成员一定要在类外面初始化? 静态成员不属于某一个类单独享有的,而是属于整个类的。通俗一点来说,就是静态成员属于公共财产,不属于私有财产。那即然是整个类所共有的话,就必定不能再类里面进行初始化,因为我们之前说过,初始化列表是给普通成员变量进行初始化,这些成员变量有个特点就是都是私有财产。

我现在来演示如何对static成员进行初始化:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//static成员的初始化
class A
{
private:
	static int _a;
};
//在类外面进行初始化
//方式:就是在变量名前指明类域
int A::_a = 10;

那我们又该如何去获取到静态成员变量里面的值呢?使用配套的static静态成员函数即可!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
public:
	static int GetStatic()
	{
		return _a;
	}
private:
	static int _a;
};
//在类外面进行初始化
int A::_a = 10;

int main()
{
	A aa;
	cout << aa.GetStatic() << endl;
}

那此是可能有的读者就会疑惑,为什么不能直接写成这样?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
public:
	int StaticNum()
	{
		return _a;
	}

private:
	static int _a;
};
//在类外面进行初始化
int A::_a = 10;

int main()
{
	A aa;
	cout << aa.StaticNum() << endl;
}

上述的写法是一个严重的错误。因为我们说过静态成员变量不是属于某个对象私有的,这也就意味着它没有隐含的this指针,如果你采用上述的写法不就自相矛盾了。

好了,有了上面的基础,我们来一道面试题:实现一个类,计算程序中创建出了多少个类对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
public:
	A() { ++_scount; }
	A(const A& t) { ++_scount; }
	~A() { --_scount; }
	static int GetACount() { return _scount; }
private:
	static int _scount;
};

int A::_scount = 0;

void TestA()
{
	cout << A::GetACount() << endl;
	A a1, a2;
	A a3(a1);
	cout << A::GetACount() << endl;
}

2.2 静态成员的特性

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

有了上面的知识做铺垫,我们来回答下面两道问题(可以在评论区中发出你们的答案):

  1. 静态成员函数可以调用非静态成员函数吗?
  2. 非静态成员函数可以调用类的静态成员函数吗?

3. 友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

友元分为:友元函数和友元类

3.1 友元函数

问题:现在尝试去重载operator<<,然后发现没办法将operator<<重载成成员函数。==因为cout的输出流对 象和隐含的this指针在抢占第一个参数的位置。==this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以要将operator<<重载成全局函数。但又会导致类外没办法访问成员,此时就需要友元来解决。operator>>同理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Date
{
public:
	Date(int year, int month, int day)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	// d1 << cout; -> d1.operator<<(&d1, cout); 不符合常规调用
	// 因为成员函数第一个参数一定是隐藏的this,所以d1必须放在<<的左侧
	ostream& operator<<(ostream& _cout)
	{
		_cout << _year << "-" << _month << "-" << _day << endl;
		return _cout;
	}
private:
	int _year;
	int _month;
	int _day;
};

友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Date
{
	friend ostream& operator<<(ostream& _cout, const Date& d);
	friend istream& operator>>(istream& _cin, Date& d);
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << "-" << d._month << "-" << d._day;
	return _cout;
}

istream& operator>>(istream& _cin, Date& d)
{
	_cin >> d._year;
	_cin >> d._month;
	_cin >> d._day;
	return _cin;
}

int main()
{
	Date d;
	cin >> d;
	cout << d << endl;
	return 0;
}

说明:

  • 友元函数可访问类的私有和保护成员,但不是类的成员函数
  • 友元函数不能用const修饰
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数的调用原理相同

3.2 友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

  • 友元关系是单向的,不具有交换性。 比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time 类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
  • 友元关系不能传递 如果B是A的友元,C是B的友元,则不能说明C时A的友元。
  • 友元关系不能继承,在继承位置再给大家详细介绍
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Time
{
	friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{}

private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}

	void SetTimeOfDate(int hour, int minute, int second)
	{
		// 直接访问时间类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}

private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

4. 内部类

概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。

注意:内部类天生就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。

4.1 内部类的特性

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
  3. sizeof(外部类)=外部类,和内部类没有任何关系。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
private:
	static int k;
	int h;
public:
	class B // B天生就是A的友元
	{
	public:
		void foo(const A& a)
		{
			cout << k << endl;//OK
			cout << a.h << endl;//OK
		}
	};
};
int A::k = 1;

int main()
{
	A::B b;
	b.foo(A());

	return 0;
};

5. 匿名对象

匿名对象十分的常用,这里我会给大家再讲一下,如何使用匿名对象以及匿名对象的一些特点。

概念:匿名对象顾名思义就是没有变量名的对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
public:
	A(int a = 1)
		:_a(a)
	{
		cout << _a << endl;
		cout << "A(int a = 1)" << endl;
	}
	~A()
	{
		cout << _a << endl;
		cout << "~A()" << endl;
	}

private:
	int _a;
};

int main()
{
	//有名对象
	A aa1(10);
	//匿名对象
	A(100);

	return 0;
}

匿名对象的使用场景:当我们只是为了使用这个类中的某些成员函数,并不在乎类中成员变量时,我们就可以使用匿名对象。

匿名对象的特点:

  • 对于普通的匿名对象来说,其的生命周期就在定义的那一行。(const匿名对象除外)
  • 遇到const匿名对象时,生命周期会被提升为当前函数的生命周期中

6. 再次理解类和对象

现实生活中的实体计算机并不认识,计算机只认识二进制格式的数据。如果想要让计算机认识现实生活中的实体,用户必须通过某种面向对象的语言,对实体进行描述,然后通过编写程序,创建对象后计算机才可以认识。比如想要让计算机认识洗衣机,就需要:

  1. 用户先要对现实中洗衣机实体进行抽象 — 即在人为思想层面对洗衣机进行认识,洗衣机有什么属性,有那些功能,即对洗衣机进行抽象认知的一个过程
  2. 经过1之后,在人的头脑中已经对洗衣机有了一个清醒的认识,只不过此时计算机还不清楚,想要让计 算机识别人想象中的洗衣机,就需要人通过某种面相对象的语言(比如:C++、JavaPython等)将洗衣 机用类来进行描述,并输入到计算机中
  3. 经过2之后,在计算机中就有了一个洗衣机类,但是洗衣机类只是站在计算机的角度对洗衣机对象进行 描述的,通过洗衣机类,可以实例化出一个个具体的洗衣机对象,此时计算机才能洗衣机是什么东西。
  4. 用户就可以借助计算机中洗衣机对象,来模拟现实中的洗衣机实体了。

在类和对象阶段,大家一定要体会到,类是对某一类实体(对象)来进行描述的,描述该对象具有那些属性,那些方法,描述完成后就形成了一种新的自定义类型,才用该自定义类型就可以实例化具体的对象。

类和对象的再次描述
类和对象的再次描述

好了,到这里本文就结束了。

如果觉得本文还不错的话,麻烦给偶点个赞吧!!!

哈哈
哈哈
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-11-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
数据源之间存在数据迁移吗?还是类似presto,跨平台查询的时候最终在上层的计算框架进行执行?
数据源之间存在数据迁移吗?还是类似presto,跨平台查询的时候最终在上层的计算框架进行执行?
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
一站式数据智能平台哪家强?腾讯云TCHouse-X深度解析
gavin1024
2025/08/22
950
云原生数智平台怎么选?腾讯云TCHouse-X全维度拆解
gavin1024
2025/08/22
940
腾讯大数据|天穹SuperSQL执行核心剖析
1. 数据孤岛:由于历史原因以及不同数据中心的业务差异性,众多异构数据源形成了数据孤岛,导致大量且繁重的人工数据搬迁。与此同时,由于不同国家的数据安全法限制,很多数据无法搬迁,数据安全和查询效率都难以保证
腾讯大数据
2024/04/28
2K0
腾讯大数据|天穹SuperSQL执行核心剖析
天穹SuperSQL:腾讯下一代大数据自适应计算引擎
导语 SuperSQL是腾讯自研的下一代大数据自适应计算平台。通过开放融合的架构,实现一套代码高效解决公有云、私有云、内网的任何大数据计算场景问题。我们通过将异构计算引擎/异构存储服务、计算引擎的智能化/自动化、SQL的流批一体、算力感知的智能调度纳入内部系统闭环,给用户提供极简统一的大数据计算体验。用户能够从繁杂的底层技术细节中解脱出来,专注于业务逻辑的实现,像使用“数据库”一样使用“大数据”,实现业务逻辑与底层大数据技术的解耦。 SuperSQL作为腾讯大数据智能计算平台的入口和决策中心,整合不同的大数
腾讯大数据
2022/08/26
5.6K0
天穹SuperSQL:腾讯下一代大数据自适应计算引擎
智能计算时代 | SuperSQL基于监督学习模型的自适应计算提效能力
点击蓝字 关注我们更多咨询 天穹SuperSQL是腾讯自研、基于统一SQL语言模型、面向机器学习智能调优、提供虚拟化数据和开放式计算引擎的大数据智能融合平台。在开放融合的Data Cloud上,业务方可以消费完整的数据生命周期(采集-存储-计算-分析-洞察),还能够满足位于不同数据中心、不同类型数据源的数据联合分析/即时查询的需求。 目前,SuperSQL已经迈入智能计算时代,SuperSQL能够基于规则匹配(RBO)与代价估算(CBO),利用不同算法智能地为不同用户SQL挑选最合适的执行引擎,极大地优化S
腾讯大数据
2022/03/03
1.3K0
《你问我答》第四期 | 进一步讲解SuperSQL、Oceanus以及Tbase
各位小伙伴们大家好,我们又见面啦~ 这里是《你问我答》栏目第四期 上周推送了一篇关于腾讯SuperSQL的文章 《「解耦」方能「专注」——腾讯天穹SuperSQL跨引擎计算揭秘》 很多同学对这个项目产生了浓厚的兴趣 本期,我们的专家老师将现身说法 进一步为大家介绍腾讯大数据SQL引擎天穹SuperSQL的性能表现 同时,也会解答小伙伴们关于 腾讯一站式实时计算平台Oceanus 以及分布式 HTAP 数据库管理系统Tbase 的部分疑问 对这些话题感兴趣的同学就快来看看吧! 01 @旧故里草木深:
腾讯大数据
2020/06/22
1.3K0
「解耦」方能「专注」——腾讯天穹SuperSQL跨引擎计算揭秘
导语:得益于调度单元是通用的SQL语句,SuperSQL能够做到与特定计算引擎解耦,也正因为此原因,SuperSQL只需专注在最优执行计划生成,并根据SQL具体类型选择最佳的计算引擎。 天穹SuperSQL是腾讯自研的跨数据源、跨数据中心、跨计算引擎的大数据SQL引擎,能够满足位于不同数据中心、不同类型数据源的数据联合分析/即时查询的需求。在腾讯整个天穹大数据图谱中,负责连接端与存储。 数据源无论是关系型数据库、NoSQL还是大数据系统;数据存储无论是跨集群还是跨数据中心;数据计算无论是报表生成、分析挖掘
腾讯大数据
2020/06/16
3.3K0
如何编译及使用TPC-DS生成测试数据
TPC-DS采用星型、雪花型等多维数据模式。它包含7张事实表,17张纬度表平均每张表含有18列。其工作负载包含99个SQL查询,覆盖SQL99和2003的核心部分以及OLAP。这个测试集包含对大数据集的统计、报表生成、联机查询、数据挖掘等复杂应用,测试用的数据和值是有倾斜的,与真实数据一致。本篇文章主要介绍如何编译及使用TPC-DS生成测试数据。
Fayson
2018/03/30
10.8K1
ByConity与主流开源OLAP引擎(Clickhouse、Doris、Presto)性能对比分析
随着数据量和数据复杂性的不断增加,越来越多的企业开始使用 OLAP(联机分析处理)引擎来处理大规模数据并提供即时分析结果。在选择 OLAP 引擎时,性能是一个非常重要的因素。因此,本文将使用 TPC-DS 基准测试的 99 个查询语句来对比开源的 ClickHouse、Doris、Presto 以及 ByConity 这 4 个 OLAP 引擎的性能表现,以便为企业选择合适的 OLAP 引擎提供参考。
深度学习与Python
2023/08/08
9660
ByConity与主流开源OLAP引擎(Clickhouse、Doris、Presto)性能对比分析
两种列式存储格式:Parquet和ORC
随着大数据时代的到来,越来越多的数据流向了Hadoop生态圈,同时对于能够快速的从TB甚至PB级别的数据中获取有价值的数据对于一个产品和公司来说更加重要,在Hadoop生态圈的快速发展过程中,涌现了一批开源的数据分析引擎,例如Hive、Spark SQL、Impala、Presto等,同时也产生了多个高性能的列式存储格式,例如RCFile、ORC、Parquet等,本文主要从实现的角度上对比分析ORC和Parquet两种典型的列存格式,并对它们做了相应的对比测试。
不吃西红柿
2022/07/29
7.7K0
两种列式存储格式:Parquet和ORC
腾讯 PB 级大数据计算如何做到秒级?
天穹 SuperSQL 是腾讯自研,基于统一的 SQL 语言模型,面向机器学习智能调优,提供虚拟化数据和开放式计算引擎的大数据智能融合平台。在开放融合的 Data Cloud 上,业务方可以消费完整的数据生命周期,从采集-存储-计算-分析-洞察。还能够满足位于不同数据中心、不同类型数据源的数据联合分析/即时查询的需求。 Presto 在腾讯天穹 SuperSQL 大数据生态中,定位为实现秒级大数据计算的核心服务。主要面向即席查询、交互式分析等用户场景。Presto 服务了腾讯内部的不同业务场景,包括微信支
腾讯技术工程官方号
2022/01/21
1.8K1
Inceptor5.1-批处理分析数据库的进阶
Transwarp Inceptor是针对于批量处理及分析的数据库,被广泛应用于数据仓库和数据集市的构建。Inceptor基于Hadoop和Spark技术平台打造,加上自主开发的创新功能组件,有效解决了企业级大数据数据处理和分析的各种技术难题,帮助企业快速构建和推广数据业务。 这是Inceptor 5.1的架构图,与5.0版本相比,其中有两个模块发生了明显变化。一个是分步执行引擎中增加了向量化执行引擎Windrunner,另一处是在分布式列存中将Holodesk构建于新引入的存储架构Shiva。 除了功
企鹅号小编
2018/02/28
2K0
Inceptor5.1-批处理分析数据库的进阶
HAWQ技术解析(一) —— HAWQ简介
一、SQL on Hadoop 过去五年里,许多企业已慢慢开始接受Hadoop生态系统,将它用作其大数据分析堆栈的核心组件。尽管Hadoop生态系统的MapReduce组件是一个强大的典范,但随着时间的推移,MapReduce自身并不是连接存储在Hadoop生态系统中的数据的最简单途径,企业需要一种更简单的方式来连接要查询、分析、甚至要执行深度数据分析的数据,以便发掘存储在Hadoop中的所有数据的真正价值。SQL在帮助各类用户发掘数据的商业价值领域具有很长历史。 Hadoop上的SQL支持一开始是Apache Hive,一种类似于SQL的查询引擎,它将有限的SQL方言编译到MapReduce中。Hive对MapReduce的完全依赖会导致查询的很大延迟,其主要适用场景是批处理模式。另外,尽管Hive对于SQL的支持是好的开端,但对SQL的有限支持意味着精通SQL的用户忙于企业级使用案例时,将遇到严重的限制。它还暗示着庞大的基于标准SQL的工具生态系统无法利用Hive。值得庆幸的是,在为SQL on Hadoop提供更好的解决方案方面已取得长足进展。 1. 对一流的SQL on Hadoop方案应有什么期待 下表显示了一流的SQL on Hadoop所需要的功能以及企业如何可以将这些功能转变为商业利润。从传统上意义上说,这些功能中的大部分在分析数据仓库都能找到。
用户1148526
2019/05/25
7.5K0
大数据领域的性能测试Benchmark介绍
一、Benchmark简介 Benchmark是一个评价方式,在整个计算机领域有着长期的应用。正如维基百科上的解释“As computer architecture advanced, it became more difficult to compare the performance of various computer systems simply by looking at their specifications.Therefore, tests were developed that all
Albert陈凯
2018/04/04
4.3K0
腾讯大数据团队主导Apache社区新一代分布式存储系统Ozone 1.0.0发布
近日,由腾讯大数据团队主导的Ozone 1.0.0版本在Apache Hadoop社区正式发布。经过2年多的社区持续开发和腾讯内部1000+节点的实际落地验证,Ozone 1.0.0已经具备了在大规模生产环境下实际部署的能力。 Ozone 是Apache Hadoop社区推出的新一代分布式存储系统,它的出现满足了大量小文件的存储问题,解决了Hadoop分布式文件系统在可扩展性上的缺陷。作为Hadoop生态圈的一款新的对象存储系统,能够支持百亿甚至千亿级文件规模的存储。 腾讯大数据团队Ozone项目负
腾讯大数据
2020/09/27
1.2K1
SQL on Hadoop在快手大数据平台的实践与优化
SQL on Hadoop,顾名思义它是基于Hadoop生态的一个SQL引擎架构,我们其实常常听到Hive、SparkSQL、Presto、Impala架构,接下来,我会简单的描述一下常用的架构情况。
Fayson
2019/07/22
1.8K0
SQL on Hadoop在快手大数据平台的实践与优化
开箱即用,腾讯数据湖计算为海量数据分析赋能
导读 / Introduction 数据湖解决了海量异构数据的入湖和存储需求。通过对海量数据的分析挖掘,提升对数据的洞察,助力数字化决策,进而促进业务发展,是每个企业构建数据湖的根本目的所在。随着业务迭代的不断加速,企业对数据时效性和数据分析敏捷性提出了更高的要求。为此,腾讯云推出了数据湖计算(Data Lake Compute,DLC)。DLC采用存储和计算分离的架构,结合腾讯云对象存储COS和弹性容器服务EKS,打造了一个开箱即用、弹性扩展、按量付费的交互式分析服务。 图1 DLC架构图 高性
腾讯大数据
2021/05/13
1.6K0
Apache Hive 是怎样做基于代价的优化的?
上一篇文章 Apache Calcite 为什么能这么流行 末尾提到要单独开一篇文章,聊下 Hive 怎么利用 Calcite 做基于代价查询优化,现在兑现承诺。
Lenis
2019/12/25
1.2K0
Apache Hive 是怎样做基于代价的优化的?
【赵渝强老师】大数据生态圈中的组件
大数据体系架构中的组件非常多,每个组件又属于不同的生态圈系统。从最早的Hadoop生态圈体系开始,逐步有了Spark生态圈体系和Flink生态圈体系。因此在学习大数据之前有必要了解一下每一个生态圈体系中具体包含哪些组件,以及它们的作用又是什么。
赵渝强老师
2024/09/04
4000
【赵渝强老师】大数据生态圈中的组件
云原生数据湖为什么要选择腾讯云大数据DLC,一份性能分析报告告诉你!
摘要 日前,腾讯云大数据数据湖计算 DLC 与国内两家知名云厂商的数据湖产品进行了性能对比,其中腾讯云 DLC 在三款产品中SQL平均执行查询时间短,性能表现优。腾讯云大数据 DLC 在存算分离和大数据量查询场景下,海量查询性能较 A 厂商 产品提升 248%,较 B 厂商产品提升36%。 在存算分离大数据量查询场景下,腾讯云大数据 DLC 较 A 厂商 、B 厂商表现更优,同时在较大任务上的任务执行成功率更高,所有任务均成功执行。结合性能、性价比、使用体验等因素,腾讯云 DLC 在云原生数据湖选择上整体上
腾讯云大数据
2022/09/09
1.9K0
云原生数据湖为什么要选择腾讯云大数据DLC,一份性能分析报告告诉你!
推荐阅读
相关推荐
一站式数据智能平台哪家强?腾讯云TCHouse-X深度解析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验