Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C+中的对象实例化是否存在显著的内在成本+;? 我最近在代码审查中(由一个更老练的C++开发人员)讲述了我改写的一个类,把它变成一组静态方法。他证明了这一点,他说,尽管我的对象确实包含非常少量的内部状态,但无论如何它都可以在运行时派生出来,如果我改为静态方法,我就可以避免在所有地方对对象进行疯狂的初始化 我现在已经做了这个改变,但是我想,C++中实例化的代价是多少?我知道,在托管语言中,垃圾收集对象的所有成本都是巨大的。但是,我的C++对象只是在堆栈上,它不包含任何虚拟方法,因此不会有运行时函数查找成本。我使用了新的C++11删除机制来删除默认的复制/分配操作符,因此不涉及复制。它只是一个简单的对象,有一个只做少量工作的构造函数(静态方法无论如何都需要),还有一个什么都不做的析构函数。你能告诉我这些装置是什么吗?(评论员有点吓人,我不想问他时显得很愚蠢!);-)_C++ - Fatal编程技术网

C+中的对象实例化是否存在显著的内在成本+;? 我最近在代码审查中(由一个更老练的C++开发人员)讲述了我改写的一个类,把它变成一组静态方法。他证明了这一点,他说,尽管我的对象确实包含非常少量的内部状态,但无论如何它都可以在运行时派生出来,如果我改为静态方法,我就可以避免在所有地方对对象进行疯狂的初始化 我现在已经做了这个改变,但是我想,C++中实例化的代价是多少?我知道,在托管语言中,垃圾收集对象的所有成本都是巨大的。但是,我的C++对象只是在堆栈上,它不包含任何虚拟方法,因此不会有运行时函数查找成本。我使用了新的C++11删除机制来删除默认的复制/分配操作符,因此不涉及复制。它只是一个简单的对象,有一个只做少量工作的构造函数(静态方法无论如何都需要),还有一个什么都不做的析构函数。你能告诉我这些装置是什么吗?(评论员有点吓人,我不想问他时显得很愚蠢!);-)

C+中的对象实例化是否存在显著的内在成本+;? 我最近在代码审查中(由一个更老练的C++开发人员)讲述了我改写的一个类,把它变成一组静态方法。他证明了这一点,他说,尽管我的对象确实包含非常少量的内部状态,但无论如何它都可以在运行时派生出来,如果我改为静态方法,我就可以避免在所有地方对对象进行疯狂的初始化 我现在已经做了这个改变,但是我想,C++中实例化的代价是多少?我知道,在托管语言中,垃圾收集对象的所有成本都是巨大的。但是,我的C++对象只是在堆栈上,它不包含任何虚拟方法,因此不会有运行时函数查找成本。我使用了新的C++11删除机制来删除默认的复制/分配操作符,因此不涉及复制。它只是一个简单的对象,有一个只做少量工作的构造函数(静态方法无论如何都需要),还有一个什么都不做的析构函数。你能告诉我这些装置是什么吗?(评论员有点吓人,我不想问他时显得很愚蠢!);-),c++,C++,可能不是很多,如果它是某种瓶颈,我会感到惊讶。但如果没有其他的事情,这是有原则的 但是,你应该问那个家伙;永远不要害怕这样做,这里不完全清楚的是,丢失存储状态并每次派生它(如果您正在这样做的话)不会让事情变得更糟。如果不是,您可能会认为名称空间比静态方法更好 一个TestScase/Expple将使它更容易地回答,而不是“你应该问他”。 < P>如果你的对象类型在生命周期中调用一个非平凡的构造函数和析构函数,那么代价就是创建任何具有一个不平凡的构造函数和析构函数的C++对象的最小代价。使其余的方

可能不是很多,如果它是某种瓶颈,我会感到惊讶。但如果没有其他的事情,这是有原则的

但是,你应该问那个家伙;永远不要害怕这样做,这里不完全清楚的是,丢失存储状态并每次派生它(如果您正在这样做的话)不会让事情变得更糟。如果不是,您可能会认为名称空间比静态方法更好


一个TestScase/Expple将使它更容易地回答,而不是“你应该问他”。

< P>如果你的对象类型在生命周期中调用一个非平凡的构造函数和析构函数,那么代价就是创建任何具有一个不平凡的构造函数和析构函数的C++对象的最小代价。使其余的方法保持静态不会降低成本。空间的“价格”将至少为1字节,因为您的类不是派生类的基类,
静态
类方法调用中唯一节省的成本将是省略作为调用的隐藏第一个参数传递的隐式
指针,非静态类方法需要的东西


如果审阅者要求您重新指定为
static
的方法永远不要接触类类型的非静态数据成员,那么传递隐式
这个
指针是浪费资源,审阅者有一个很好的观点。否则,您必须向静态方法添加一个参数,该参数将类类型作为引用或指针,通过省略隐式
指针来抵消所获得的性能。

作为一般规则,如果函数可以设置为静态,则它可能应该是静态的。它更便宜。便宜多少?这取决于对象在构造函数中所做的事情,但是构造C++对象的基本成本并不高(当然,动态内存分配更昂贵)。
关键是不要为你不需要的东西付钱。如果一个函数可以是静态的,为什么要使它成为成员函数?在这种情况下,作为成员函数是没有意义的。创建对象的惩罚会影响应用程序的性能吗?可能不会,但再说一遍,为什么要为不需要的东西付费呢?

这取决于应用程序的功能。它是内存有限的设备上的实时系统吗?如果不是的话,大多数时候对象实例化都不会成为问题,除非你实例化了数百万个对象并保持它们不变,或者像这样的奇怪设计。 大多数系统将有更多的瓶颈,例如:

  • 用户输入
  • 网络电话
  • 数据库访问
  • 计算密集型算法
  • 线程转换成本
  • 系统调用

我认为在大多数情况下,封装到一个类中进行设计胜过实例化的小成本。当然,可能有1%的情况下,这不成立,但你是其中之一?

简短回答-本质上,对象分配是便宜的,但在某些情况下可能会变得昂贵

长答案

<>在C++中,实例化对象的成本与实例化C中的结构相同。所有对象都是一个大内存块,足以存储V-TABLE(如果它有一个)和所有数据属性。方法在v表实例化后不再消耗内存

非虚方法是一个简单函数,其第一个参数为隐式
this
。调用虚拟函数有点复杂,因为它必须通过v表查找才能知道调用哪个类的哪个函数

这意味着在堆栈上实例化一个对象涉及到堆栈指针的简单减量(对于完全去中心堆栈)

当在堆上实例化对象时,成本可能会大幅上升。但这是任何与堆相关的分配所固有的。在堆上分配内存时,堆需要找到一个足够大的空闲块来容纳对象。查找这样一个块是一个非恒定时间操作,可能会很昂贵

C++的构造函数可以为某些指针数据属性分配更多内存。这些通常是堆分配的。如果所述数据成员自己执行堆分配,这将进一步加剧。这可能导致涉及大量指令的事情


所以归根结底,这取决于你如何以及你的目的是什么。

正如其他人所建议的那样,与你的同事谈谈,让他解释他的理由。如果可行,您应该使用一个小测试程序进行调查
#include <algorithm>
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>

bool int_lt(int a, int b)
{
    return a < b;
}

int
main()
{
    size_t const N = 50000000;
    std::vector<int> c1;
    c1.reserve(N);
    for (size_t i = 0; i < N; ++i) {
        int r = rand();
        c1.push_back(r);
    }
    std::vector<int> c2 = c1;
    std::vector<int> c3 = c1;

    clock_t t1 = clock();
    std::sort(c2.begin(), c2.end(), std::less<int>()); 
    clock_t t2 = clock();
    std::sort(c3.begin(), c3.end(), int_lt);
    clock_t t3 = clock();

    std::cerr << (t2 - t1) / double(CLOCKS_PER_SEC) << '\n';
    std::cerr << (t3 - t2) / double(CLOCKS_PER_SEC) << '\n';

    return 0;
}
> g++-4.5 -O2 p3.cc 
> ./a.out 
3.85
5.88
#include <iostream>
#include <time.h>
#include <vector>
#include <stdlib.h>

typedef long (*fp_t)(long, long);

inline long add(long a, long b)
{
    return a + b;
}

struct add_fn {
    long operator()(long a, long b) const
    {
        return a + b;
    }
};

long f(std::vector<long> const& x, fp_t const add, long init)
{
    for (size_t i = 0, sz = x.size(); i < sz; ++i)
        init = add(init, x[i]);
    return init;        
}

long g(std::vector<long> const& x, add_fn const add, long init)
{
    for (size_t i = 0, sz = x.size(); i < sz; ++i)
        init = add(init, x[i]);
    return init;        
}

int
main()
{
    size_t const N = 5000000;
    size_t const M = 100;
    std::vector<long> c1;
    c1.reserve(N);
    for (size_t i = 0; i < N; ++i) {
        long r = rand();
        c1.push_back(r);
    }
    std::vector<long> c2 = c1;
    std::vector<long> c3 = c1;

    clock_t t1 = clock();
    for (size_t i = 0; i < M; ++i)
        long s2 = f(c2, add, 0);
    clock_t t2 = clock();
    for (size_t i = 0; i < M; ++i)
        long s3 = g(c3, add_fn(), 0);
    clock_t t3 = clock();

    std::cerr << (t2 - t1) / double(CLOCKS_PER_SEC) << '\n';
    std::cerr << (t3 - t2) / double(CLOCKS_PER_SEC) << '\n';
    return 0;
}
> g++ -O2 p5.cc 
> ./a.out 
0.87
0.32