为什么我要在C++;? 我最近发现C++中存在 *>代码>运算符(以及密切相关的 -> */Cux>运算符)。(见问题。)

为什么我要在C++;? 我最近发现C++中存在 *>代码>运算符(以及密切相关的 -> */Cux>运算符)。(见问题。),c++,pointer-to-member,C++,Pointer To Member,一开始看起来很整洁,但我为什么需要这样的东西呢?链接问题中的两个答案提供了一些人为的示例,这些示例将受益于直接函数调用 如果直接函数调用不方便,则可以使用函数对象,例如可以在std::sort中使用的lambda函数。这消除了一定程度的间接性,因此比使用*性能更好 链接问题还提到了该示例的简化版本: struct A { int a; int b; }; void set_member(A& obj, int A::* ptr, int val){ obj.*p

一开始看起来很整洁,但我为什么需要这样的东西呢?链接问题中的两个答案提供了一些人为的示例,这些示例将受益于直接函数调用

如果直接函数调用不方便,则可以使用函数对象,例如可以在
std::sort
中使用的lambda函数。这消除了一定程度的间接性,因此比使用
*
性能更好

链接问题还提到了该示例的简化版本:

struct A {
    int a;
    int b;
};

void set_member(A& obj, int A::* ptr, int val){
    obj.*ptr = val;
}

int main()
{
    A obj;
    set_member(obj, &A::b, 5);
    set_member(obj, &A::a, 7);
    // Both members of obj are now assigned
}
但是这样做非常简单(也许更好的做法是因为它更干净,并且不需要不必要地约束
A
的成员):

struct A {
    int a;
    int b;
};

void set_me(int& out, int val){
    out = val;
}

int main()
{
    A obj;
    set_me(obj.b, 5);
    set_me(obj.a, 7);
    // Both members of obj are now assigned
}
总之,指向成员函数的指针可以被函数对象替换,指向成员变量的指针可以被所述变量或函数对象的直接引用替换。这样做还可能由于减少了一个间接寻址而提高代码的效率

问题只提供了我的结论的例子,所以它不能回答我的问题


除了连接使用
*
的遗留代码(在该代码中没有任何选择)之外,我什么时候真的想使用
*

您可以创建指向成员的指针集合并对其进行迭代。例如:

struct UserStrings
{
    std::string first_name;
    std::string surname;
    std::string preferred_name;
    std::string address;
};

...

std::array<std::string UserStrings::*, 4> str_cols = { &UserStrings::first_name, &UserStrings::surname, &UserStrings::preferred_name, &UserStrings::address };
std::vector<UserStrings> users = GetUserStrings();

for (auto& user : users)
{
    for (auto& column : str_cols)
    {
        SanitizeForSQLQuery(user.*column);
    }
}
struct UserStrings
{
std::string first_name;
std::字符串姓氏;
std::字符串首选名称;
std::字符串地址;
};
...
std::array str_cols={&UserStrings::first_name,&UserStrings::name,&UserStrings::preferred_name,&UserStrings::address};
std::vector users=GetUserStrings();
用于(自动和用户:用户)
{
用于(自动列:str_cols(&U))
{
SanitizeForSQLQuery(用户。*列);
}
}

<代码> > p>让你说,为C++编写一个LINQ风格库,可以使用这样的东西:

struct Person
{
    std::string first_name;
    std::string last_name;
    std::string occupation;
    int age;
    int children;
};

std::vector<Person> people = loadPeople();
std::vector<std::string> result = from(people)
     .where(&Person::last_name == "Smith")
     .where(&Person::age > 30)
     .select("%s %s",&Person::first_name,&Person::last_name);
for(std::string person : result) { ... };
struct-Person
{
std::string first_name;
std::字符串last_name;
std::字符串占用;
智力年龄;
智力儿童;
};
std::vector people=loadPeople();
标准::向量结果=来自(人)
.where(&Person::last_name==“Smith”)
.其中(&人::年龄>30岁)
。选择(“%s%s”、&Person::first\u name、&Person::last\u name);
对于(std::string person:result){…};
在封面下,
where
函数接受一个表达式树,其中包含一个指向成员(以及其他内容)的指针,并应用于每个向量项,寻找一个匹配项。
select
语句接受一个格式字符串和一些指向成员的指针,并对通过
where
语句的任何向量项执行
sprintf
样式的格式化


我写过类似这样的东西,还有一些其他的东西做的稍有不同()。指向成员的指针允许库用户指定他们想要的结构的任何成员,而库不需要知道他们可能做什么。

它用于实现
std::mem\u fn
,用于实现
std::function

下面的代码显示了
->*
操作符如何在简单的
函数
类实现中工作

类似地,可以使用
*
操作符和类引用实现成员调用器类

#include <iostream>

class A
{
public:
    void greet()
    {
        std::cout << "Hello world"<<std::endl;
    }
};

template<typename R, typename ...TArgs>
class Invoker 
{
public:
    virtual R apply(TArgs&& ...args) = 0;
};

template<typename C, typename R, typename ...TArgs>
class MemberInvoker :public Invoker<R, TArgs...>
{
protected:
    C*                          sender;
    R(C::*function)(TArgs ...args);

public:
    MemberInvoker(C* _sender, R(C::*_function)(TArgs ...args))
        :sender(_sender)
        , function(_function)
    {
    }

    virtual R apply(TArgs&& ...args) override
    {
        return (sender->*function)(std::forward<TArgs>(args)...);
    }
};

template<typename T>
class Func
{
};

template<typename R, typename ...TArgs>
class Func<R(TArgs...)>
{
public:
    Invoker<R,TArgs...>* invoker=nullptr;

    template<typename C>
    Func(C* sender, R(C::*function)(TArgs...))
    {
        invoker =new MemberInvoker<C, R, TArgs...>(sender, function);
    }

    R operator()(TArgs&& ...args)
    {
        return  invoker->apply(std::forward<TArgs>(args)...);
    }

    ~Func()
    {
        if (invoker)
        {
            delete invoker;
            invoker = nullptr;
        }
    }
};

int main()
{
    A a;
    Func<void()> greetFunc(&a, &A::greet);
    greetFunc();
    system("PAUSE");
}
#包括
甲级
{
公众:
无效问候()
{

STD::CUT

你的例子太琐碎了,不能说明问题。

struct A {
    int a;
    int b;
};

void set_n_members(A objs[], unsigned n, int A::* ptr, int val)
{
  for (unsigned i = 0; i < n; ++i)
     objs[i].*ptr = val;
}

int main()
{
    A objs[100];
    set_n_members(objs, 100, &A::b, 5);
    set_n_members(objs, 100, &A::a, 7);
}
结构A{ INTA; int b; }; void set_n_成员(A objs[],无符号n,int A::*ptr,int val) { for(无符号i=0;i

在没有
int A:::*ptr
和不引起代码膨胀的情况下,您如何重写这篇文章?

可能重复的内容可能您正在思考一些琐碎的示例,需要真正做一些高级示例,但我想这不是应该做的地方that@Stargateur我更新了我的问题,解释了为什么其他问题的答案都不是satisfactory.@GuillaumeRacicot No.我以前写过类似的东西,但我只是在
PropertyImpl
中添加了第三个模板参数,这是一个可调用的参数,只需使用
Class
类型的单个参数,并返回对正确成员的引用。毕竟,您已经在使用模板了。这样,元组的类型元素封装了足够的信息以找到正确的成员,无需存储指向成员的指针。@Bernard问题是,确保您可以在不使用指向成员的指针的情况下编写所有代码。在不使用指向成员的指针的情况下,总有另一种实现方法。但有时,指向成员的指针会使事情变得更加复杂更易于编写,这证明了它们的使用是正确的。使用模板可以加快速度,并且不需要比示例更多的代码。请参阅我的版本。@Bernard:但在一般情况下,它会导致代码膨胀。在现实生活中,决定是使用运行时参数(上述)还是编译时参数(模板)这不是一件容易的事。所以你关于“使用模板使速度更快”的论点太原始了。模板的代价是代码膨胀,如果有更大的函数,这可能是巨大的。模板化代码的正确设计包括知道何时切换到运行时参数化,以抑制不必要的代码膨胀。当涉及到成员选择时,指向成员的指针正是运行时参数化的工具on.
&Person::last\u name==“Smith”
怎么能编译呢?另外,如果
std::find\u
std::remove\u
work t