C++ 成员函数作用域变量

C++ 成员函数作用域变量,c++,static,scope,C++,Static,Scope,考虑以下代码: #include <iostream> struct X { int foo() { // Can I get this to be an instance-specific static variable, please? static int i = 0; return i++; } }; int main() { X a, b; std::cout << a.foo(

考虑以下代码:

#include <iostream>

struct X {
    int foo() {
        // Can I get this to be an instance-specific static variable, please?
        static int i = 0;
        return i++;
    }
};

int main() {
    X a, b;
    std::cout << a.foo() << ' ';
    std::cout << b.foo() << ' ';
    std::cout << b.foo() << '\n';
    // output is: 0 1 2
    // desired output: 0 0 1
}
而不是去做这样的事情:

struct B {
    int j = 0;
    std::function<int()> foo = 
        [this, i = 0]() mutable { return i++ + this->j++; };
};
或者这个:

struct C {
    int j;
    struct Foo {
        int i; 
        C *c;
        Foo(C *c) : i(), c(c) {}
        int operator() () { return i++ + c->j++; }
    } foo;
    C() : j(), foo(this) {}
};
struct D {
   int j = 0;
   std::map<std::string, int> i;
   int foo() { return i[__PRETTY_FUNCTION__]++ + j++; }
};
struct D{
int j=0;
地图一;
int foo(){return i[uu PRETTY_FUNCTION_uu]+++j++}
};
或类似的

非常感谢您的评论和回答

不,这是不可能的

您可以选择两个选项:

  • 将变量设为成员,这是具有所需语义的语言特性
  • 或者发明一种新的语言

  • 我确实理解你的担忧,但这实际上只是因为你的
    显然太大了。将其职责分开。

    可能这就是您想要的:

    struct X {
        X() : i(0) {}  // initialize variable on construction
    
        int foo() {
            // Can I get this to be an instance-static variable, please?
            return i++;
        }
    
        int i; // instance variable
    };
    
    编辑:不带成员变量的备选方案,适用于不寻求简单选项的用户:

    typedef std::map<X*,int> XMap;
    static XMap xMap;
    
    struct X {
        X() { xMap.insert(this, 0); }
        ~X() { xMap.erase(this); }
    
        int foo() {
            return xMap[this]++;
        }
    };
    

    foo
    X
    的唯一方法吗?似乎您只是想要一种方便的方法来创建计数器,然后:

    #include <functional>
    
    std::function<int()> create_counter()
    {
        int i = 0;
        return [=]() mutable { return i++; };
    }
    
    #include <iostream>
    
    int main()
    {
        auto a = create_counter();
        auto b = create_counter();
    
        std::cout << a() << '\n';
        std::cout << a() << '\n';
        std::cout << b() << '\n';
        std::cout << b() << '\n';
        std::cout << b() << '\n';
        std::cout << b() << '\n';
        std::cout << a() << '\n';
    }
    
    #包括
    std::函数create_counter()
    {
    int i=0;
    return[=]()可变{return i++;};
    }
    #包括
    int main()
    {
    自动a=创建_计数器();
    自动b=创建_计数器();
    
    std::cout您可以创建一个方法
    GetVariableI(X)
    ,该方法将接受X的实例并返回实例特定的值,或者在传递null时返回静态值

    这种方法应该能解决你的问题,尽管它很愚蠢。它能满足你说的你想要的,但几乎可以肯定不是你需要的。你想要达到的行为是什么?如果你能详细说明你想要达到的目标,我们可以提供另一种(明智的)解决方案。

    轮到我了:

    struct X {
        class _foo {
            int i;
        public:
            _foo() : i(0) { }
            int operator()(void) {
                return i++;
            }
        } foo;
    };
    

    基本上,函数静态变量使函数成为对象(身份、状态、行为)。您只是不希望它是单例。因此,它是一个类。

    您可以通过Knuth查看。它确实是这样做的。基本上,您需要一种可以在文本中移动的宏语言。

    您可以将函数状态封装在lambda中,包含在
    std::function
    成员中:

    #include <functional>
    #include <iostream>
    struct X {
        std::function<int()> foo = [i = 0]() mutable { return i++; };
    };
    int main() {
        X a, b;
        std::cout << a.foo() << " " << b.foo() << " " << b.foo() << std::endl;
    }
    
    #包括
    #包括
    结构X{
    函数foo=[i=0]()可变{return i++;};
    };
    int main(){
    xa,b;
    
    std::cout扩展了Valeri Atamaniouk的答案,并稍微混淆了它,这样做似乎不需要任何成员变量

    struct X {
        int foo() {
            struct l_int {
                int i;
                l_int():i(0) {};
            };
            static std::map<X*,l_int> i_map;
            return (i_map[this]).i++;
        }
    };
    
    struct X{
    int foo(){
    结构l_int{
    int i;
    l_int():i(0){};
    };
    静态标准::映射i_映射;
    return(i_map[this]).i++;
    }
    };
    
    我不宽恕它,因为我认为它很可怕,而且当你试图复制对象时可能会失败,但你做到了。而且,是的,每次你销毁一个对象时,它确实会泄漏一点内存

    将值存储在结构中的原因是,当您在
    std::map
    中创建一个新条目时,可以确保它将被初始化为零,这将在调用
    foo()
    时发生在每个新对象上


    该程序将
    0 1 0
    作为输出,但我参考了上面关于求值顺序的评论。

    这里是另一个选项。从概念上讲,它不是很清晰,但它确实解决了将函数和变量更紧密地放在一起的技术问题,同时保持相当简单:

    struct XFoo {
        XFoo() : i(0) { }
    
        int foo() { return i++; }
    
        private:
            int i;
    };
    
    struct X : XFoo {
      // lots of stuff here
    };
    
    或使用C++11:

    struct XFoo {
        int foo() { return i++; }
    
        private:
            int i = 0;
    };
    


    那么你想要一个特定于实例的静态变量吗?如果它在类/结构中使用,这是否违背了
    静态
    的目的?不,你不能这样做,你必须使它成为类成员。句号。说得小一点,你不想要静态变量。你想要的是函数范围的成员变量。它不是静态的。我听说了你陈述两个目标(1)你需要的功能(2)你认为是很漂亮的软件工程目标。不幸的是,C++只给你一种获取(1)的方式,它似乎没有满足你的想法(2)。.据我的理解,这三个函数调用不是可以按任何顺序求值,因此理论上您的输出可以是“0 2 1”?这也意味着您所需的输出也可以是“0 0 1”。不确定计算顺序是如何受ostreams影响的,注意。这会产生所需的输出,但它并不完全是我想要的。事实上,这正是我不想要的。@moooeeep,但这是唯一的方法。想想编译器是如何知道这些的:在哪里为变量分配空间?哪个变量属于特定的instace?onl方法是使它成为实例的一个成员。是的,可能我正在为这个确切的东西寻找语法糖。@ValeriAtamaniouk注意到“静态映射”选项还要求类重载其复制构造函数和复制赋值运算符以保持映射同步-我认为这是不值得的。@ValeriAtamaniouk正是如此,因此
    0
    ()。最后即使它没有(但它确实),
    insert
    已经足够了,因为它还可以检查是否存在。每个实例是否都会得到不同版本的
    foo
    ?将其设置为
    静态
    ,它将是我答案的浓缩版本。你必须看两遍,但至少初始化离我有点近:)@PeterWood我想要每个实例使用C++11,你可以在类中初始化
    i
    ,并将类转换为匿名结构,然后你就有了一些非常简单的东西。这看起来很有趣-我的例子当然大大简化了。更具体地说,我想跟踪最后一个调用参数和最后一次调用的时间调用(计算两次调用之间的持续时间)不幸的是,当我完成X时,这会泄露内存。我从来没有说过它是完美的:“Lexness CraceSein轨道它封装在一个可调用的成员中,它改善了文本的位置。@ AlvinWong,C++,JDK有什么用?”马尔科姆,我想我应该说GCC,但是……(我的大脑受伤了)
    struct X {
        int foo() {
            struct l_int {
                int i;
                l_int():i(0) {};
            };
            static std::map<X*,l_int> i_map;
            return (i_map[this]).i++;
        }
    };
    
    struct XFoo {
        XFoo() : i(0) { }
    
        int foo() { return i++; }
    
        private:
            int i;
    };
    
    struct X : XFoo {
      // lots of stuff here
    };
    
    struct XFoo {
        int foo() { return i++; }
    
        private:
            int i = 0;
    };