C++ 像C+一样大量使用共享ptr造成的性能损失+;正在收集垃圾?
我想知道引用计数的C++ 像C+一样大量使用共享ptr造成的性能损失+;正在收集垃圾?,c++,performance,shared-ptr,C++,Performance,Shared Ptr,我想知道引用计数的shared_ptrs的性能问题,因此我编写了一个哑巴程序,它以一种非常低效的方式计算pow(2,n),使用数百万的内存分配和释放,以测试shared_ptrs,同时不让编译器优化一切,即使完全优化 用, g++ t.cpp -std=c++11 -ot -DV_ -pedantic -Ofast -s -fwhole-program 其中-DV_uu表示使用std::vector作为容器 作为 valgrind ./t 10000 这意味着要计算pow(21000)告诉我
shared_ptr
s的性能问题,因此我编写了一个哑巴程序,它以一种非常低效的方式计算pow(2,n)
,使用数百万的内存分配和释放,以测试shared_ptr
s,同时不让编译器优化一切,即使完全优化
用,
g++ t.cpp -std=c++11 -ot -DV_ -pedantic -Ofast -s -fwhole-program
其中-DV_uu表示使用std::vector
作为容器
作为
valgrind ./t 10000
这意味着要计算pow(21000)
告诉我
total heap usage: 45,174,051 allocs, 45,174,051 frees, 783,160,061 bytes allocated
及
输出
real 0m1.698s
user 0m1.693s
sys 0m0.004s
考虑到堆分配完成的数量,这是惊人的快。该系统是一台配备i5cpu和Ubuntu Linux操作系统的笔记本电脑
我在这里使用的基本模式是定义容器类,将shared_ptr
扩展到其原始类
#if defined(V_)
#define C_ std::vector
#elif defined(L_)
#define C_ std::list
#elif defined(D_)
#define C_ std::deque
#else
#error
#endif
template<typename T>
class Container : public std::shared_ptr<C_<T>>
{
public:
Container():
std::shared_ptr<C_<T>>(new C_<T>)
{
}
};
class String : public std::shared_ptr<std::string>
{
public:
String():
std::shared_ptr<std::string>(new std::string)
{
}
String(const char* s):
std::shared_ptr<std::string>(new std::string(s))
{
}
const char* getCString()
{
return get()->c_str();
}
};
请注意,共享_ptr并不打算从中继承,至少不是公共继承和多态行为。一种方式是缺乏虚拟函数和虚拟析构函数。我认为“垃圾收集”的想法从根本上是误导的。正如Eric Raymond所说,垃圾收集模拟无限内存。C++没有垃圾收集,而且不会产生垃圾;相反,它产生了所有权和责任。共享指针的用途是表示共享所有权。使用共享指针,当你需要共享所有权时,“java或C++都能提供比C++更好的效率”——你问的是关于共享指针的基本问题,告诉我们C++比那些语言同时生产力低?“KerrekSB,你是说Raymond Chen不?”(我起初以为这篇文章是埃里克·利珀特写的,后来我的大脑表现出了未定义的行为。)
#if defined(V_)
#define C_ std::vector
#elif defined(L_)
#define C_ std::list
#elif defined(D_)
#define C_ std::deque
#else
#error
#endif
template<typename T>
class Container : public std::shared_ptr<C_<T>>
{
public:
Container():
std::shared_ptr<C_<T>>(new C_<T>)
{
}
};
class String : public std::shared_ptr<std::string>
{
public:
String():
std::shared_ptr<std::string>(new std::string)
{
}
String(const char* s):
std::shared_ptr<std::string>(new std::string(s))
{
}
const char* getCString()
{
return get()->c_str();
}
};
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <memory>
#if defined(V_)
#define C_ std::vector
#elif defined(L_)
#define C_ std::list
#elif defined(D_)
#define C_ std::deque
#else
#error
#endif
void check(bool isOkay)
{
if (!isOkay)
{
std::exit(EXIT_FAILURE);
}
}
template<typename T>
class Container : public std::shared_ptr<C_<T>>
{
public:
Container():
std::shared_ptr<C_<T>>(new C_<T>)
{
}
};
class String : public std::shared_ptr<std::string>
{
public:
String():
std::shared_ptr<std::string>(new std::string)
{
}
String(const char* s):
std::shared_ptr<std::string>(new std::string(s))
{
}
const char* getCString() const
{
return get()->c_str();
}
};
class SlowInteger : public Container<int>
{
public:
SlowInteger()
{
}
SlowInteger(int n)
{
check(0 <= n && n < 20);
if (n < 10)
{
get()->push_back(n);
}
else
{
get()->push_back(n - 10);
get()->push_back(1);
}
}
int toInt() const
{
if (get()->size() == 1)
{
return get()->front();
}
else
{
return get()->front() + 10 * get()->back();
}
}
};
class VerySlowInteger : public Container<SlowInteger>
{
public:
VerySlowInteger(String stringNumber)
{
for (auto it = stringNumber->rbegin(); it != stringNumber->rend(); ++it)
{
get()->push_back(SlowInteger(*it - '0'));
}
}
void x2()
{
int m = 0;
for (auto it = get()->begin(); it != get()->end(); ++it)
{
int n = it->toInt() * 2;
if (n < 10)
{
*it = SlowInteger(m + n);
m = 0;
}
else
{
*it = SlowInteger(n - 10 + m);
m = 1;
}
}
if (m == 1)
{
get()->push_back(SlowInteger(1));
}
}
void x2n(int n)
{
check(n > 0);
for (int i = 0; i < n; ++i)
{
x2();
}
}
String toString()
{
String s;
for (auto it = get()->rbegin(); it != get()->rend(); ++it)
{
s->push_back(it->toInt() + '0');
}
return s;
}
};
int main(int argc, char **argv)
{
check(argc == 2);
int n = std::atoi(argv[1]);
check(n > 0);
VerySlowInteger nSlow("1");
nSlow.x2n(n);
String s = nSlow.toString();
std::cout << s.getCString() << std::endl;
return EXIT_SUCCESS;
}