什么是c ++指针的示例用法?

时间:2010-07-02 10:10:07

标签: c++ pointers

我是自学c ++,我得到了指针的工作方式。但我正在使用的文档是非常文字的,并且示例并没有真正说明为何或何时使用指针。一些现实世界的例子可以帮助我保留知识。

10 个答案:

答案 0 :(得分:9)

当您希望对象存在的时间长于当前堆栈时,可以使用指针。您也可以使用它们来避免将对象复制到容器中。

// TODO: Remember to call DeleteObjects() when you're done here!!
std::vector<MyObject*> Objects;

void Test()
{
    MyObject *const pObject = new MyObject();
    Objects.push_back(pObject);
}

void DeleteObjects()
{
    std::vector<MyObject*>::iterator it = Objects.begin(), itEnd = Objects.end();
    for (; it != itEnd; ++it)
    {
        delete *it;
    }
    Objects.clear();
}

答案 1 :(得分:3)

这不是一个容易回答问题的简单问题,而且我确信有很多资源在讨论指针。基本上,无论何时你想使用间接(甚至可能是递归),你都需要指针。

例如说一个二叉树数据结构,其中每个节点都有指向它的左右子树的指针,其中任何一个可能指向0(或NULL,表示无效指针)以表示没有子树那里。这个结构可能看起来像这样(不是很C ++ - y,但这是一个不同的故事)

struct TreeNode
{
  TreeNode* left;
  TreeNode* right;
}

在这种情况下你不能使用任何指针,因为它是一个无限大的结构。

答案 2 :(得分:1)

  1. 从函数上传多个数据。调用者将提供要由函数
  2. 覆盖的内存位置的地址
  3. 动态内存分配。分配器将返回指向新分配对象的指针。
  4. 传递数组参数:传递地址而不是复制,以保存常量数据的性能。

答案 3 :(得分:1)

当您需要一个函数来返回多个变量时,指针很有用。例如,考虑一下您在杂货店购物。每个产品都有名称和价格。名称将是一个字符串,价格为双倍。如果有一个名为“buy”的函数,并且您想要返回该项的名称和价格,则可能需要使用指针。

答案 4 :(得分:1)

这不是C ++的问题,而是C问题。对于初学者,我很乐意推荐这本书Understanding Pointers in C

答案 5 :(得分:1)

指针的一个简单示例是链接列表。有关wikipedia的更多信息。

答案 6 :(得分:0)

void print_values(int* iptr, int size)
{
    int i;
    for (i=0; i < size; i++)
    {
        printf("%d ", *(iptr++));
    }
    printf("\n");
}

int main()
{
    int table[256];
    memset(table, 0, sizeof(table));
    print_values(table, sizeof(table)/sizeof(int));
}

或者像一组函数(例子):

#define ___FUNC_B { func_1, func_2, func3 }
void ( __closure __fastcall * __FUNC_B [__FUNC_MAX] )( TObject* ) = ___FUNC_B;

按指针使用对象在很多情况下更好:

CClass *ptr = new CClass();
/* something */
delete ptr;

如果您有许多对象,并且您必须以某种方式(例如,排序)获取它,您可以使用指针来指向非对象的对象:

vector <CClass*> Vptr;
for (i=0; i < 100; i++)
{
    Vptr.push_back(new CClass());
}

sort(Vptr.begin(), Vptr.end(), __cmp_func);
/* something */

while (!Vptr.empty())
{
    delete *(Vptr.begin());
    Vptr.erase(Vptr.begin());
}

用C语言进行动态内存分配:

char *memory = (char*) malloc(1024);
if (memory == NULL)
{
    exit(1);
}

/* you have alocated 1KB in memory */
memory = (char*) realloc(2048);
if (memory == NULL)
{
    exit(1);
}

/* you have alocated 2KB in memory */
free(memory);
/* you have nothing */

答案 7 :(得分:0)

  

是c ++的一个示例用法   指针?

指针解决了以下问题:

  • 避免复制大块内存。至少在C语言中,在C ++中,首选方法是使用引用。如果你愿意,你仍然可以使用指针。

  • 在运行时分配内存。当您不知道编译将使用多少内存时,需要这样做。

  • 记住延迟调用(和回调)的(成员)函数的地址。

  • 分配超出当前范围的内存(在范围完成后仍然分配)。

  • 在多个实体(多个对象,多个线程等)之间共享对象。这意味着您可以传递对象的地址,使用它的所有实体都将访问相同的数据,而不是相同的副本。

有时指针也用作句柄。也就是说,如果您希望允许客户端代码唯一地标识数据块而不关心(或知道)数据是什么,则将数据的地址(指针)转换为int /某些其他类型并将其传递为一个手柄。这通常在提供客户端代码句柄的API中找到,但不允许客户端代码访问实际数据(请参阅使用WinAPI的HANDLE,HWND等 - 这些是内部实现中的指针,但您不知道 - 或者关心 - 为了使用它,实际数据是什么。)

答案 8 :(得分:0)

好的,我看到了很多可怕的反应,我觉得自己有义务再增加一个。

首先要做的事情是:我们在这里谈论C ++。如此多的C使用完全失效。

指针的可怕用途

你应该学习RAII :这个例子在面对异常时是完全不安全的

// BAD
void func(size_t n)
{
  int* array = new int[n];
  // .. use array
  delete[] array;
}

// GOOD
void func(size_t n)
{
  std::vector<int> array(n, 0);
  // .. use array
}

经验法则:如果你看到delete,那你做错了。如果你看到new,也有可能因为参数转发问题而不是真的。

尽可能使用参考

// BAD: Contract: do not pass NULL
void func(int* i);

// GOOD
void func(int& i);

每当传递NULL没有意义(并且您不需要重新绑定)时,请使用普通值或(const)引用而不是指针。

指针的良好用途

混叠

void printSorted(std::vector<BigType> const& values)
{
  std::vector<BigType*> references = from(values);

  std::sort(references.begin(), references.end(), ByPointer());

  std::transform(references.begin(), references.end(),
                 std::ostream_iterator<BigType>(std::cout, " "),
                 Dereference());
}

可选结果

Object* find(Key const& key);

这相当于:

boost::optional<Object&> find(Key const& key);

但不那么冗长。

克隆方法

使用裸指针作为clone方法的返回类型是由Boost Cloneable概念强制执行的:

struct Base
{
  virtual ~Base() {}

  virtual Base* clone() const = 0;
};

有一个合理的理由:利用协变返回类型来重载虚拟方法。这允许我们写:

struct Derived: Base
{
  virtual Derived* clone() const { return new Derived(*this); }
};

因此,当从Derived const&克隆时,充分利用我们知道返回的内容至少 a Derived

遗憾的是程序员需要处理已分配的内存,因此必须与Smart Containers一起使用:

std::unique_ptr<Base> u = derived.clone();

答案 9 :(得分:-1)

指针可以被视为一个简单的变量,但不是保存值,而是将地址保存到存储值的内存位置。

将记忆视为一个抽屉,在每个抽屉中你可以设置一个值,以便更容易找到值,你可以抽出几个抽屉。因此,记忆的位置将是抽屉,而块将是完整的记忆。

因此,当您创建指针时,例如:

int* drawer = 0;

你指的是标有数字0并且包含整数值的抽屉,现在你可能会想,好吧,但是,我怎样才能得到这个值?嗯,这很简单:

int value = *drawer;

以同样的方式,您可以在该抽屉上存储新值(内存地址):

*drawer = 15;

现在很有趣,抽屉柜很神奇,抽屉可以把你带到街区的另一个抽屉里,如果我们用相同的数字标记它们,那么一个存储的价值在另一个中是相同的:< / p>

int* drawer = 0;
int* drawer_copy = drawer;
*drawer = 15;

会发生什么? “drawer_copy”,将地址0称为“抽屉”,允许您访问整数值15。

我们还可以保存正常变量的地址,我们使用“&amp;”获得该地址的前缀:

int value = 15;
int* drawer = &value;

如果我们现在这样做:

value = 5;

“*抽屉”将返回5。

正如您所看到的,指针允许用户对内存进行更多控制并永久保留内存,一旦声明了指针,就可以保留地址并随时访问它。 :)