我创建了一个库,想知道设计是否效率低下
I created a library and was wondering if the design is inefficient
在我的库设计中,我构造了很多对象,想知道这是否会导致它效率低下。
我创建了一个库来创建并运行查询。查询是一个类,它采用对Bind
对象的initializer_list
的右值引用。每个Bind
都有一定的价值。
我认为设计效率低下,因为如果我们使用const char*
s,每个Bind
对象都将复制其值,但字符串除外。最重要的是,我们必须为每个值构造一个完整的Bind
对象。然后,我将所有Bind
四舍五入到一个initializer_list
中,并将它们移动到一个vector
中,我不确定那里有多少开销。这是在Query
对象中创建的,该对象可能构造成本不高,并且只创建一个Query
对象。
查看代码片段底部的main
函数可能是您需要查看的全部内容。
class Database {
public:
Database() = default;
~Database() = default;
Result run(Query&& query);
};
class Query {
public:
Query(const char* query, std::initializer_list<Bind>&& binds);
~Query() = default;
...
private:
std::string m_query;
std::vector<Bind> m_binds;
};
Query::Query(const char* query, std::initializer_list<Bind>&& binds) : m_query(query), m_binds(binds) {}
class Bind {
friend Query;
public:
explicit Bind(int32_t i);
explicit Bind(int64_t i);
explicit Bind(uint32_t i);
explicit Bind(float f);
explicit Bind(const char* str);
private:
int bind(sqlite3_stmt* stmt, int column);
ColumnType m_type;
union {
int64_t m_i;
float m_f;
const char* m_str;
};
size_t m_str_size;
};
int main()
{
Database db;
auto result = db.run(Query(
"INSERT INTO users VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
Bind(id),
Bind(first_name),
Bind(last_name),
Bind(age),
Bind(height),
Bind(weight),
Bind(siblings),
Bind(hometown),
Bind(mom),
Bind(dad),
Bind(num_pets),
Bind(os::time_since_epoch()),
Bind(location),
Bind(json),
}));
return 0;
}
内部std::initializer_list<T>
只是几个指针。这些没什么可搬到那里的。因此,按&&
接受它没有多大意义。标准库按值获取它,我建议你以同样的方式进行。Bind
也没有什么可移动的。
如果所有构造函数只有一个参数Bind
则可以创建一个可变参数构造函数并使用emplace_back()
就地构造每个Bind
:
class Query {
public:
template<class... Bind_args>
Query(const char* query, Bind_args&&... bind_args) {
m_binds.reserve(sizeof...(Bind_args));
(m_binds.emplace_back(std::forward<Bind_args>(bind_args)), ...);
}
private:
std::vector<Bind> m_binds;
};
这将简化Query
施工
query("INSERT INTO users VALUES (?, ?, ?)", 1, "33", 2.f);
如果没有分析,很难判断它是否会更有效率。如今,编译器(和链接器(可以非常擅长代码优化,您描述的所有这些开销可能会完全优化。
如果带有折叠表达式的 C++17 不可用,则可以将折叠表达式替换为 C++11 版本:
int sink[] = {(m_binds.emplace_back(std::forward<Bind_args>(bind_args)), 0)...};
(void)sink;
Bind
接口需要支持多个参数
然后可以将这些参数打包到元组中:
class Query {
public:
template<class... Tuples>
Query(const char* query, Tuples&&... bind_arg_tuples) {
m_binds.reserve(sizeof...(Tuples));
(emplace_from_tuple(std::forward<Tuples>(bind_arg_tuples)), ...);
}
private:
template<class Tuple>
void emplace_from_tuple(Tuple&& arg_tuple) {
emplace_from_tuple(std::forward<Tuple>(arg_tuple),
std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>{});
}
template<class Tuple, std::size_t... is>
void emplace_from_tuple(Tuple&& arg_tuple, std::index_sequence<is...>) {
m_binds.emplace_back(std::get<is>(std::forward<Tuple>(arg_tuple))...);
}
private:
std::vector<Bind> m_binds;
};
query("INSERT INTO users VALUES (?, ?, ?)",
std::tuple(1, 2), std::tuple("33", "44"), std::tuple(2.f, 3.f));
此代码避免调用Bind
的复制构造函数,并正确移动所有参数(包括仅移动类型,如std::unique_ptr
(。但对于轻量级Bind
对象来说,这可能是不必要的过度复杂化。
- 我想知道长双倍和双倍之间的区别
- 我是 C++ 的初学者,我想知道如何在 2D 矢量中获取重复值
- C++新手,想知道如何使用VS code 2019播放音频文件
- 我是C++新手,我想知道,为什么在c ++中使用纯虚函数?为什么要使用纯虚函数?
- 我想知道为什么"std::unique_ptr<int> foo(新 int)"是合法的,因为"std::<int>unique_ptr"要求输入参数类型应该是"int"?
- 我想知道我是否可以将一个类分配给特定的成员数据并创建该类的实例
- 我想知道变焦和轨道在哪里出了问题
- 我创建了一个库,想知道设计是否效率低下
- 想知道我哪里错了
- 我想知道我将如何实现 + 运算符重载.我已经从我上一个问题中计算出 += 运算符重载
- 我想知道是否有任何功能或方法可以首先检查文件是否已创建
- 语法错误,也想知道我是否可以使这段代码更有效率
- 我想知道进程的 BSS 段是否可以在程序执行期间增长
- 我编写了一个C++程序来打印单词字母的排列.我想知道是否有其他更简单的方法可以做到这一点
- 我想知道你是否可以告诉我imread和cvLoadImageM之间的区别
- 我试着去理解OOP,想知道我的函数是否完成得正确
- 只是想知道是否有可能有数据丢失
- 我想知道我是否可以使用智能指针
- C++ 我知道数组长度,但想知道是否是一种更简洁的数组元素定义方法
- 想知道较低版本的Visual Studio是否可以使用使用较高版本的Visual Studio构建的dll