- 主题:我们很多同事都是完全不用unique_ptr,一律shared_ptr
就是“无脑”。跟无脑用递归锁是一样的。
但归根结底,是因为没有“规则”和惩罚,只靠个人品味。
--
修改:z16166 FROM 123.115.134.*
FROM 123.115.134.*
智能指针不是为了释放资源的吗?即使没回调函数,也有释放资源的需要
Rust的borrow推导也是从另一个角度干的类似的事情,追踪引用的计数,但区分了read、write
【 在 hgoldfish 的大作中提到: 】
: 在我看来,智能指针、各种泛型编程,都是大量使用回调函数的后遗症。本来就不应该存在。
:
--
修改:z16166 FROM 123.115.134.*
FROM 123.115.134.*
unique_ptr的申请和释放是可以在同一个scope内的呀
【 在 foliver 的大作中提到: 】
: 本质上都是因为申请和释放不在一起导致的。
:
--
FROM 123.115.134.*
“有没有人用”,这个就是shared_ptr的引用计数。所以你还是要手动去实现shared_ptr的机制。
【 在 tortelee 的大作中提到: 】
: 也不一定吧。
: 我能想到的一个代替方案是,在event loop里面注册个函数,检查资源是否有人用,没有人用,就自动销毁。
: 多线程只负责用,不负责销毁。所以完全用不到sharedptr.
: ...................
--
FROM 111.199.144.*
就事论事,不用说太远,哈哈
【 在 tortelee 的大作中提到: 】
: 你这么说, listener设计模式,都可以用sharedptr代替了
:
: :
--
FROM 111.199.144.*
c++里拼接字符串多简单
【 在 ylh1969 (没谱) 的大作中提到: 】
: 看我的字符串组装程序:
: p+=sprintf(p,"format",,,);
: 用于生成SQL语句。
: p总是指向字符串的尾部,下一个成分直接接上。
--
FROM 218.12.20.*
这可不是语言的问题,而是这个level的语言(靠近机器的无GC的语言)都要面临这个问题。
比如Rust有Box<T>、Rc<T>、Arc<T>。
也就是说,如果你不需要区分unique_ptr和shared_ptr,那么你实际上很可能可以换用别的语言来实现你的需求,比如js或者py,这样就不用关心这个level的问题。
再一个,unique_ptr和shared_ptr不属于语法范畴,只是库。
【 在 iamiiami 的大作中提到: 】
: 如果少数人这样是人的问题。如果很多人这样用,那就是语言的问题了。c++不在基础库上发力,语法发展得都快读不懂了。
--
修改:z16166 FROM 111.199.144.*
FROM 111.199.144.*
如果还需要c_str()这种操作,那说明代码还在用字符串指针,还是用pure C的风格在写代码
另外,sprintf()也是pure C的搞法,C++的搞法是std::format()或者fmt::format(),强调编译期的type-safe检查。
【 在 ylh1969 的大作中提到: 】
: cout << .. << ..
: string << .. << :
: 最后,stmt=string.cstr();
: ...................
--
FROM 111.199.144.*
pure C的我没兴趣搞了。
AI给的modern c++方式的:
#include <iostream>
#include <string>
#include <sstream>
#include <tuple>
// ---- 反射机制 ----
template<typename T>
struct Field {
std::string_view name;
T const* ptr;
};
#define REFLECTABLE(...) \
static auto reflect_fields(const auto& self) { \
return std::make_tuple(__VA_ARGS__); \
}
#define FIELD(member) Field{#member, &self.member}
// ---- 用户结构体 ----
struct Employee {
int id;
double salary;
std::string name;
REFLECTABLE(
FIELD(id),
FIELD(salary),
FIELD(name)
)
};
// ---- SQL 生成 ----
template<typename T>
std::string SQL_insert(std::string_view table, const T& obj)
{
auto fields = T::reflect_fields(obj);
std::ostringstream sql;
sql << "INSERT INTO " << table << " (";
bool first = true;
std::apply([&](auto&&... f) {
((sql << (first ? (first = false, "") : ",") << f.name), ...);
}, fields);
sql << ") VALUES (";
first = true;
std::apply([&](auto&&... f) {
((sql << (first ? (first = false, "") : ",") << ":" << f.name), ...);
}, fields);
sql << ")";
return sql.str();
}
// ---- 调试输出 ----
template<typename T>
void SQL_bind_and_debug(const T& obj)
{
auto fields = T::reflect_fields(obj);
std::apply([&](auto&&... f) {
(([&] {
using FieldType = std::decay_t<decltype(*f.ptr)>;
if constexpr (std::is_same_v<FieldType, int>)
std::cout << "Bind int :" << f.name << " = " << *f.ptr << "\n";
else if constexpr (std::is_same_v<FieldType, double>)
std::cout << "Bind double :" << f.name << " = " << *f.ptr << "\n";
else if constexpr (std::is_same_v<FieldType, std::string>)
std::cout << "Bind string :" << f.name << " = '" << *f.ptr << "'\n";
}()), ...);
}, fields);
}
// ---- 测试 ----
int main()
{
Employee e{1001, 55000.5, "Alice"};
auto sql = SQL_insert("employee", e);
std::cout << sql << "\n";
SQL_bind_and_debug(e);
}
【 在 ylh1969 的大作中提到: 】
: 补充一点,数据库操作,可以使用离散变量或struct。
: 但是离散变量,我没办法写出通用函数,所以必然要通过一个技术:
: Struct Relational Mapping ,相当于JAVA的ORM。结构体与数据库表结构的对应。
: ...................
--
FROM 111.199.144.*
C++现在还没反射(提案阶段,没正式标准),所以反射struct的字段那个搞法,和pure C是差不多的,但可以用模板。
sql语句是变参的,用C++的变参模板来拼接sql字符串是最合适的(不考虑拼接字符串可能带来的sql注入漏洞等问题的话)。
【 在 ylh1969 的大作中提到: 】
: ok,我慢慢看。步骤差了许多,原理看看行不行。
--
FROM 111.199.144.*